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.