简体   繁体   中英

Why is my C program slower than its C# equivalent?

I've wanted to do a small benchmark test between C and C#, so I wrote the following programs:

C:

int main()
{
    int i = 1;
    while (i <= 500000)
    {
        printf("%d", i);
        i++;
    }
}

C#:

class Program
    {
        static void Main(string[] args)
        {
            int i = 1;
            while (i <= 500000)
            {
                Console.Write(i);
                i++;
            }
        }
    }

And then I compiled them and ran both at the same time.

To my surprise, the C# program has exited about 5 seconds earlier than the C program.

C is a language well-known for its high speed and great performance, so how could it be that in this case, the C# program outperformed the C program significantly in such a simple task? I thought that C# is much slower because it compiles in runtime, but it easily defeated the native executable that was compiled from C.

What is the reason for this, and does this also happen in other types of programs?

I ran these 2 programs on Windows 8.1 Pro 64-bit, if that matters, and compiled the C# program in C# Express 2010, and the C program in VS2013 Express for Desktop.

And please don't bash me for "such a common question" - Yes, I've seen another answers, but they all dealt with complex things such as memory management and buffer size, and the programs in here are very simple and do not deal with those things.

I've also tried replacing printf for puts , but that was just as slow.

Benchmarking how fast a programming language can write to the console is worthless. That's the bottleneck in both of these cases, and it's screwing up your results. The execution time of one of the programs, either the C or C# version, would vary wildly from one run to the next. So any comparisons between the two languages are meaningless.

If you really want to test the performance difference, one way to do it would be to write a complicated mathematical algorithm and benchmark that. Don't write the result to the console, though—you now know that would defeat the purpose! Also, time it using a high-resolution timer. In C#, you'd use the Stopwatch class ; in C (at least on Windows), you'd call the QueryPerformanceCounter function . Timing with a real stopwatch is just too error-prone. Or at least it is for me. Either way, make sure you query these values outside of the code you're testing.

This does not have anything to do with the C language or its compiler, everything to do with its runtime support library. The slow-down is caused by you using printf().

The C Runtime Library (CRT) is badly stuck in the mud, modeling a runtime environment that harks back to the 1970s. Back when programmers used a teletype to talk to a computer, one that had a very primitive operating system that didn't support goodies like threading, talking in English.

That runtime environment is a very drastic mismatch with modern operating systems,considerable overhead is needed to emulate it. The C language in general has pretty poor support for Unicode for example. So every string you output has to be painstakingly converted to the native operating system's string format, utf-16 in Windows. The .NET Framework uses System.String, a string type that's encoded in utf-16 as well. Even down to the lowest level, Windows requires string to be zero-terminated, just like C strings need to be. Every .NET string is automatically zero-terminated, even the ones you don't use for I/O. So no conversion is required, the framework can directly call the operating system function that outputs the string.

That's not where it ends. The notion of threading is completely alien to the CRT, it was never designed to consider the ramifications of multiple threads, say, modifying the locale or simultaneously writing text. So the CRT is peppered with low-level locks to bring this to a good end. Overhead that is very rarely actually useful, but must be taken because the 1970s runtime model doesn't disallow nor account for it.

You can make your C program just as fast as your C# program, making it noticeably faster is a bit stretch, but you have to bypass the 1970s to do so. Using wprintf() instead already ought to make a noticeable difference, you don't get parity until you call WriteConsoleW() or WriteFile().

Do note that this does not actually matter at all. The text is scrolling across the screen far faster than a human can read it anyway. So it is not a real problem that anybody would consider fixing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM