Saturday, May 4, 2013

C++ vs C#: Performance

Most programmers know that performance isn't the most important consideration when picking a language.  Ease of use and community support are also important.  Typically it's wise to pick the highest-level language that can meet the demands of the application, to use the right tool for the job.

My job is game development.  More and more games are being written completely in higher-level languages like C# and Java, which certainly have their advantages.

Last year, I was working on a C# game engine, because I like C# and because it's good enough for a lot of games.  But I was curious about just how much slower it is for a game engine than C++.  So I put together a simple C#-only demo (using OpenTK) that draws a bunch of 3D textured cubes and bounces them around inside the view volume.  Each cube is drawn and animated every frame.  I also implemented dynamic batching whereby individual cubes are combined into 1 draw call.  Then I pumped up the number of cubes until the frame rate got down to ~30 fps (~34 ms per frame).

I ended up with 25600 cubes being drawn and moved each frame.  My PC is starting to age, but I have a Core i7 processor with 8 cores (but the test app is single threaded), 12 GB of RAM, and an nVidia GeForce 8600 GTS video card.

Then I wrote a C++ version of the test app using OpenGL and freeglut.  It did exactly the same thing: the same geometry, the same texture, the same algorithm for bouncing, the same number of cubes.  It looked identical in every way, and it ran more than twice as fast (~13 ms per frame).

If you google "c# c++ performance comparison", you'll get a host of articles comparing performance between the two and other languages, like Java.  I found quite a few claiming that C# is only 10-20% slower than C++, which IMO, makes C# the clear choice.  But there are others that say C# is only half the speed of C++, which is what I found for this case.  To be clear, C# isn't so much slower for every case, and it's perfectly suited to a wide array of applications, including many games.

So after seeing the difference between pure C# and pure C++, I was curious how a hybrid would perform.  I wrote the core app in C++ which embedded the mono runtime and performed all the batching and rendering.  The C++ code loaded a C# assembly which instantiated the cubes and performed the "game logic" of bouncing the cubes around.  I wanted to emulate the way game engines like Unity use mono: C++ engine + game logic in C#.  Again, this hybrid test app produced exactly the same output as the C# and C++ versions, and it ran just a little more slowly than the pure C++ version (~15 ms per frame).

The code for all 3 apps is here.  I built and ran these apps on linux, and so I can't vouch for windows.  I used Eclipse for the C++ version and QT Creator for the hybrid.  I used Mono Develop for the C# code.

A couple other notes:
  • The C# code does not perform any memory allocations during the game loop, so garbage collection isn't an issue at all.
  • The hybrid version uses unsafe code in order for the C# and C++ sides to share the same memory.  Specifically, the C# code updates the positions and velocities of the cube in the same memory that the C++ code then reads when it renders the cubes.  I don't know how Unity does it, but I would imagine that marshaling that data across the C#/C++ boundary would only make it slower.  The code in the zip file shows how I did it.
Conclusion

So did I continue with my C# engine?  Nope.  It was a close call, but I thought that the types of games that I want to make might cause a pure C# game to bog down (like Minecraft does (which is an awesome game...I'm not ragging on it)).  I ran into this situation with Now Boarding.  It performed great until we started getting closer to the end after adding more and more visual content.  Since I'm starting a business now, laying a new foundation for future work, I don't want to get stuck later with a code base I can't make fast enough.  So I decided to lay C# aside and pick C++ back up again.

What about the hybrid version?  Isn't it the best of both worlds?  Yes and no.  Mono is a fast, extremely functional runtime, and it is pretty easy to embed in applications.  But it's a giant runtime with all kinds of features I don't need.  It's also not completely free.  Integrating a scripting language with an engine is a lot of work (I've done it with lua, and I started with mono), and in the end I decided to stick with pure C++.

There are a couple of questions that naturally follow:
  • Isn't the productivity of C# worth the runtime cost?
  • Why would you write your own engine anyway?
I'll write about those separately.

18 comments:

  1. Thank you for sharing your point of view. I am a newcomer to gaming and was asking me this exact same question.

    Your post is very reassuring of my C++ decision!

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  3. I like the article, I have myself noticed that the performance speed of C# In really complicated 3D Graphics is low,
    I created sort of a micro-minecraft C# Program using OpenTK, It was quite slow and C++ Is definitely faster. But from my experiance the C# OpenTK Is so neat and self-explanatory where as the C++ OpenGL Is (sorry) quite messy compared to C# OpenTK.
    So if performance is a problem definetely chose C++,
    otherwise I suggest C# OpenTK :).

    ReplyDelete
    Replies
    1. I agree, Samuel! I really enjoyed OpenTK when I used it.

      Delete
    2. I don't know your code, but I did a minecraft like clone in Python couple of months ago. No problems with FPS. It only depends of the algorithms you use, languages are of from minor importance. Modern OpenGL does only need a few "draw-calls" after setting up all geometries. I read those pro-C++ comments all over the internet, it's mostly deprecated knowledge. OpenGL's design has drastically changed in 3.3 and 4.2.... I can definitely suggest reading OpenGL super bible..

      Delete
  4. Thanks for posting this, it's been very helpful.

    I've been trying to decide between straight c++ and c# for a game. After reading this, I'm fairly certain that c# is the way to go.

    The performance penalty isn't enough to overcome the speed of development bonus (for my case).

    Despite coming to a different conclusion, your post definitely helped. Thanks for taking the time.

    ReplyDelete
  5. C++ is faster in your case because native call overhead is non-existing. You are not exactly comparing languages here. A managed runtime will never call native methods at the same speed as C++ does. No magic here. But the differences are not that huge. You could reduce the number of calls if you would use more modern OpenGL calls. Gosh, even python + opengl binding should be able to render huge scenes at 60FPS. It really doesn't matter for real life.

    What you are doing is premature optimization. You code in C# or Java or whatever and check if you really need native code performance.

    Developing in C++ sucks, it takes much more time and much more code and then you get only a bit more performance, I would really think about this twice.

    You could write C++ bindings later on to improve performance. I did so much 3D work, believe, it just doesn't matter. C# has such a beautiful framework and very highlevel syntax features. C++ should finally be retired.

    ReplyDelete
    Replies
    1. Thanks, Christopher, that's interesting.... What could I do to make the C# code I tried faster then?

      Delete
    2. Good read, and a valid reply.

      Delete
  6. Protection of IP is more beneficial than speed. Give me your c#/Java/other vm language game and it's protected assets and I'll rip all of your code and assets in about 10 minutes. Obfuscation does little to help. Doing this with assembly is much more time intensive. I've done both many times. If it's open source then C# or Java are probably a good choice.

    ReplyDelete
  7. Hi. Great article! The link to the sorce code for the 3 tests you did, is dead. If you still have it lying around i would love to check it out. Thanks :)

    ReplyDelete
  8. Thank you! I was a bit conflicted about which language to use, probably because I haven't done c++ in a while. Thanks for re-assuring me.

    ReplyDelete
  9. This blog awesome and i learn a lot about programming from here.The best thing about this blog is that you doing from beginning to experts level.

    Love from

    ReplyDelete