~/imallett (Ian Mallett)

Recently, I was asked to summarize my views on the subject of C#, a programming language developed, pushed for, and used primarily by, Microsoft, along with its almost inseparable graphics toolkit, XNA.

If you just want the short version of my analysis:

C# is a proprietary, non-portable, slow, poorly-implemented, feature-deficient, overall incompetent knockoff of Java. Java is suboptimal, but C# is worse in almost every way. XNA, C#'s almost inseparable graphics toolkit, is occasionally convenient, but it is slow and broken. These downsides are tempered by FOSS attempts to reinvent their wheels from scratch, but ultimately C# and XNA are evil, bad technologies that try poorly to fill a niche that doesn't—or shouldn't—exist.

The longer version, including my personal experience:

I have had the misfortune to use C#/XNA for real, if small-scale, development. My first experience was some years ago, when I was compelled to write two indie games from scratch using C# and XNA—one I took on individually, the other with a small team.

My conception of the language was initially positive. I knew from the outset that using XNA proper meant limiting myself to Windows-only platforms (clearly a Bad Thing), but, that accepted, I was at first pleased that C# was 1, very similar to Java, which I already knew, and 2, seemed to have a number of things Java lacked—in particular operator overloading and destructors. Some nice features, like Visual Studio's integrated section folding and refactoring functionality were highly appreciated.

Still, some very convenient features were still missing—macros and multiple inheritance being the two most inconvenient. Well, the world can't be perfect. So I worked on. I was pleased that I was able to rapidly prototype my ideas. While the switch from XNA 3 to 4 occurring at that time made finding consistent, relevant code snippets difficult, I made good progress learning the oddities that every language has and the graphics functionality XNA provided.

Since I pride myself on making programs having beautiful graphics (indeed as a perfectionist, I seldom release finished products since they don't), I wanted to take XNA's graphics capabilities to the max. Well, I did. Abruptly. My laptop, which was more than decent for the time, could barely handle PCF shadowmapping in XNA. What? So, I dug through all the algorithms and everything. I checked that it wasn't being software rasterized. I assumed it wasn't my fault. But, after thoroughly profiling the graphics routines and writing an OpenGL program that did the exact same thing in C++, I had to conclude that C# and XNA was just fundamentally slower.

I was disappointed, of course, but the difference was "only" 35% or so. So I pressed on, adding a physics engine, some decent lighting, particle systems, the works—toning down the effects I would ordinarily have used.

I soon decided it was time to test deployment on the XBox360. After a few problems, I got it working . . . and was horrified. What had been running smoothly at 60Hz on my laptop was now running at about than 8Hz on the XBox360. Keep in mind that my dual-core laptop, with its crappy graphics chipset, was somehow managing to best a three core CPU plus a GPU more than six times as powerful.

While the debugging facilities on the XBox360 are necessarily somewhat limited, the Internet is bountiful and I soon traced the problem to the Physics engine I was using—which used floating point calculations, naturally (since every processor for more than a decade has optimized floating point support through an integrated FPU, including, obviously, the Xenon processor used by the 360, which has an on-core FPU for each of its three cores).

Put succinctly, what I surmised was that C# emulates all floating point calculation on the XBox360. No good reason came forward, although many I talked to suspected it was a way of keeping indie developers in line.

Well fine.

I hacked out the core physics library functions with my own integer arithmetic versions, which gave me about a 740% speedup on the 360 (and about a 5% slowdown on my laptop). That ordeal over, though somewhat disgruntled, I was feeling better about the projects, if my patience was somewhat thin.

Then, some of our testers noticed something. It was subtle, but as the game grew more complicated, it became more and more obvious: the game was stuttering. It would run fine at 60Hz, but then it would choke for a quarter second or so. Since this wasn't a well-known problem then, it took me some days to conclusively arrive at the answer: C#'s garbage collection. It turns out that every now and again, the C# runtime decides to compact and delete all the dynamically allocated memory that is no longer needed ("garbage collection"). The fact that it decided to do it all at once was what was distressing. Amortizing the operation over the intervening time (or even three or four frames) would have been better.

So I dug around, and found some hints I could pass to the garbage collector. I told it to garbage collect every frame . . . and it completely ignored me.

I rooted around a bit, and since I am very careful with memory management by nature, I concluded that I was not allocating and deleting anything at all during gameplay (I had to temporarily disable the physics engine). Yet the program still stuttered.

At the time, I concluded that the stack variables were actually being allocated on the heap internally, though I had no technical evidence to support that. Somewhat later, I did make a simple test XNA application that did nothing at all and allocated every single variable at file scope, but still observed stuttering. I can only conclude that the C# runtime itself was allocating and deleting memory for operations that it clearly shouldn't.

Anyway, I capped the framerate at 30 fps, and the stuttering became (less) noticeable. To this day, I get the occasional email from people who have the same story and tried the same fixes to no avail—so I assume Microsoft's C# implementation never fixed the problem.

Performance issues discouraged us, and the team project never came to fruition because the artists were too distraught by the limited rendering capabilities XNA was able to provide. So the project was ultimately a failure.

My individual game, I actually finished. It won a few small awards, but on the XBox360, there was still stuttering if you looked closely. And the graphics were still terrible by my standards. Recent testing revealed a major internal bug in the XNA rendering layer prevents it from working properly on modern hardware. I haven't the time nor interest to find a workaround.

So overall? C# gave some promising beginnings, and developing with XNA was initially somewhat gratifying. But, in the end, when I tried to do anything real, I found myself limited by the poor implementation of the language. I know that Visual Studio isn't the only C# compiler around (though, as I hear it, it's the best), but at this point, why bother? Java does everything C# does and it has much better support and implementation. I hate Java and I'm finding myself recommending it over C#.

I know there are FOSS projects (notably Mono), that try to make C# (and XNA) not suck. But again—why bother? C++ is much less finicky than any interpreted language when it comes to memory, and OpenGL provides much lower-level graphics and therefore is much better suited for real game development. Surprise that that's what major game developers use (though it's often C++ and Direct3D instead of C++ and OpenGL, for mainly historical (wrong) reasons).

Update: it develops that XNA has been officially canceled. I, for one, applaud the decision.


COMMENTS
Ian Mallett - Contact -
Donate
- 2021 - Creative Commons License