I found out that there is real test than the little one I did here. The core of the post is this spreadsheet :

Graph

I recently did a basic comparison test between C++ (g++) and C# .Net (mono).

My point is to show that the .Net framework has performances close to the C++ ones. It allows automatic hardware-specific optimization. The only real drawback you have in the .Net framework is the garbage collector. It prevents the C# .Net it from being a realtime language/framework. But does it really matter for you ?

The purpose of the following test is to show that C++ isn’t faster than C# “as is”. I KNOW C# can not be faster than C++ because C# can do few hardware specific optimizations when you can do all of them in C++, because all the systems calls have to be done in C/C++ and because there’s no such thing like Template and forced inlining in C#.

But if you’re searching for arguments to choose C# .Net over native C++, you should also consider these :

  • C# is much more simple. No headers, the languages specifications are simple and clear
  • You don’t have to manage the memory in .Net (simplified code, no memory leak, optimal memory consumption)
  • C# code is as portable as java, it doesn’t need to be manually ported to a new architecture like C++
  • .Net don’t just crash; they always throw an exception, and they only crash if nothing catches it
  • Mono (and presumably the .Net framework) does some really interesting optimizations:
$ mono --list-opt

Here are some links related to interesting optimizations used by the Mono .Net framework:

FlagDetails
peepholePeephole postpass
branchBranch optimizations
inlineInline method calls
cfoldConstant folding
conspropConstant propagation
copypropCopy propagation
deadceDead code elimination
linearsLinear scan global reg allocation
cmovConditional moves
sharedEmit per-domain code
schedInstruction scheduling
intrinsIntrinsic method implementations
tailcTail recursion and tail calls
loopLoop related optimizations
fcmovFast x86 FP compares
leafLeaf procedures optimizations
precompPrecompile all methods before executing Main
aotUsage of Ahead Of Time compiled code
abcremArray bound checks removal
ssapreSSA based Partial Redundancy Elimination
exceptionOptimize exception catch blocks
ssaUse plain SSA form
sse2SSE2 instructions on x86
gsharedShare generics
simdSimd intrinsics
  • Multithreading in .net is much easier than any other language. You even have the parrallel loop operations, like Parallel.For.

SO ! Here is the test

I wrote these two sample programs :

One in C++ :

#include <iostream>
using namespace std;
 
long stupidThing( long nb ) {
    long out = 1;
    while( nb >  )
        out *= nb--;
 
 
    return out;
}
 
int main() {
 
    long total = ;
 
    for( int i = ; i < 1000000; ++i )
        for( long l = ; l < 100; ++l )
            total += stupidThing( l );
 
    cout << "Total : " << total << endl;
 
    return ;
}

One in C#:

using System;
 
namespace test {
    class Program {
        static long stupidThing( long nb ) {
            long ret = 1;
            while ( nb >  )
                    ret *= nb--;
            return ret;
        }

        static void Main( string[] args ) {
            long total = ;

            for ( int i = ; i < 1000000; ++i )
                    for ( long l = ; l < 100; ++l )
                            total += stupidThing( l );
            Console.WriteLine( "Total : {0}", total );
        }
    }
}

First of all, I open a shell in real-time priority because I don’t want my other processes to mess with my tests :

$ rtprio 99 bash

Then I compile the two programs :

$ gmcs test.cs
$ g++ -O4 test.cpp -o test

And then I launch my test :

On a 64 bits host :

uname -a
Kernel : 2.6.9-023stab051.3-smp #1 SMP Wed Nov 4 18:36:34 MSK 2009 x86_64 x86_64 x86_64 GNU/Linux
$ time ./test ; time ./test ; time ./test ; time mono test.exe ; time mono test.exe ; time mono test.exe
Total : -6192109806162068864
real    0m12.433s
user    0m12.394s
sys     0m0.049s

Total : -6192109806162068864
real    0m12.415s
user    0m12.411s
sys     0m0.014s

Total : -6192109806162068864
real    0m12.430s
user    0m12.411s
sys     0m0.026s

Total : -6192109806162068864
real    0m10.311s
user    0m10.287s
sys     0m0.029s

Total : -6192109806162068864
real    0m10.254s
user    0m10.247s
sys     0m0.011s

Total : -6192109806162068864
real    0m10.250s
user    0m10.255s
sys     0m0.012s

C# clearly beats C++ here. Well

On a 32 bits host :

$ uname -a
Kernel : 2.6.30-2-686 #1 SMP Fri Dec 4 00:53:20 UTC 2009 i686 GNU/Linux
$ time ./test ; time ./test ; time ./test ; time mono test.exe ; time mono test.exe ; time mono test.exe
Total : 100461056

real    1m10.927s
user    1m7.376s
sys     0m0.056s
Total : 100461056

real    1m12.590s
user    1m8.976s
sys     0m0.020s
Total : 100461056

real    1m13.279s
user    1m9.532s
sys     0m0.056s
Total : -6192109806162068864

real    2m22.492s
user    2m15.260s
sys     0m0.136s
Total : -6192109806162068864

real    2m23.002s
user    2m15.760s
sys     0m0.104s
Total : -6192109806162068864

real    2m25.102s
user    2m17.709s
sys     0m0.144s

C++ beats C# here, but in 32 bits C++ use other types whereas C# use the same. In C# long is always 64 bits, in C++ it can be 64 bits or 32 bits (depending on the current architecture).