Why is there a huge difference in performance between the C++ Debug version and the Release version, but not C#?

Viewed 69

In some large-scale C++ projects, the Debug version is almost useless, such as some game engines UnrealEngine, Ogre3d, etc. Because the Debug version of the program is too stuck to run, it is almost unusable. But when I was developing a C# program, I was surprised to find that the difference in experience between the Debug version and the Release version of the C# application was not so great that it was impossible to distinguish between debug and release. why?

// test C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace ConsoleApp21
{
    internal class Program
    {
        static void DoSomething()
        {
            StringBuilder builder = new StringBuilder();
            for(int i=0;i<10000000; ++i)
            {
                builder.Append(i.ToString());
            }

            Console.WriteLine($"{builder.ToString().Length}");
        }

        static void Main(string[] args)
        {
#if DEBUG
            Console.WriteLine("DEBUG:");
#else
            Console.WriteLine("Release:");
#endif

            Stopwatch sw = Stopwatch.StartNew();

            DoSomething();

            Console.WriteLine(sw.Elapsed.ToString());
        }
    }
}

DEBUG: 68888890 00:00:00.9831842

Release: 68888890 00:00:00.8958183

// test cpp code
#include <iostream>
#include <string>
#include <boost/progress.hpp>

void DoSomething()
{
    std::string str;
    char buf[64];

    for (int i = 0; i < 1000000; ++i)
    {
        sprintf_s(buf, "%d", i);
        str.append(buf);
    }

    std::cout << str.size() << std::endl;
}

int main()
{
#ifdef _DEBUG
    printf_s("DEBUG:");
#else
    printf_s("RELEASE:");
#endif

    boost::progress_timer timer;
    
    DoSomething();
}

DEBUG:5888890 0.33 s

RELEASE:5888890 0.06 s

1 Answers

One reason is that c++ can optimize more. Since all work is done ahead of time it can spend however much time it wants on figuring out the optimal way to convert the code. .Net compiled by the just-in-time compiler (jitter), and therefore need to compile code fast, so it does not have time for any costly optimization. Newer .Net releases support tiered compiling, so could allow more optimization for frequently used code.

There might also be restrictions in what optimization can be applied since c# and .Net is more focused on ensuring correctness and developer productivity than the performance focused mentality of c++.

Note that attaching a debugger to .Net code will disable some types of optimizations, so you need to be careful when doing any comparisons. You also need to be careful with c++ code, since some higher level of optimizations can cause the compiler to just remove entire sections of code if there is some undefined behavior. Also check that the c++ code uses high precision timers, and not the computer clock. I would not be surprised if something named "progress" would use the later.

Related