Thursday, December 20, 2007

Why Do We Use C++?

One of the recurring questions (especially when confronted with concurrency) is 'why do we use C++ for game development?' This entry was extracted from Concurrency in Game Development since it's really a separate topic all its own and that one was overlong anyway.

Why Do We Use C++?

Now before I hear the platitudes about how [insert favorite non-C++ language here] is better anyhow and would fix everything in one shot, let me ask you how feasible it would be to develop multi-million line software on multiple, often brand-new, platforms simultaneously with extreme performance expectations, leveraging mega/gigabytes of shared legacy code and without having to port, develop and/or maintain one's own compilers and toolsets with this superior language. If the game development industry turns to non-C++ languages to solve this, it will be slowly and painfully. And, most likely, it will be an industry-wide move and not just one studio or another, although some must lead the way. Honestly, I would never expect C++ to go away completely (just as assembly has never really gone away), and some future approaches may just be layered on top of C++ (Bigloo, Intel Ct, OpenMP), or use it when performance is critical (Java's JNI).

C++ is flexible and fast. With sufficient (possibly enormous) effort, it can do almost everything any language can do. It can function both as a high-level multiparadigm language and as a low-level portable assembly language. What makes C++ (and C) so widespread is its unrestrictive nature. This is widely seen as a negative, but in the real world, being able to abuse your language to get what you want from your machine is of crucial importance - especially when performance is a primary concern. That said, you may only want to abuse your language say 2-5% of the time. The rest (95-98%) of the time, you'd like some nice, type-safe, bounds checking, memory-managed, interactive, memoizing language, giving you a >100% increase in productivity. That we have settled on C++ indicates that the 2-5% is so crucial that we're willing to sacrifice the rest for it. In the game industry, I think that's a fair statement.

Another, often forgotten strength of C++ and of many traditional modular and modular-turned-OO languages is linking, or more generally, we might say 'package management'. C++ innately offers build-time linking and runtime 'linking' is also usually available (i.e., DLLs). This allows graceful scaling. Tool support for this in C++ is strong and reasonably robust because C++ is so frequently used to build enormous projects. It's possible to build massive projects in pieces in ways that are awkward or impossible in many functional or logic languages. (See comments, some strong points about other languages package handling vs C++'s and Which Languages Handle Packages and Libraries Best?)

Still, writing solid C++ code even in the absence of multithreading requires a mastery of nearly the whole language, making it dangerous for inexperienced developers. Even merely adequate C++ coding is heavily reliant on learned idioms that are not a part of the language, and therefore unenforceable. For example, that you are allowed to return a pointer or reference to a stack-allocated object from a function, or that you are allowed to overflow a string buffer have cost the world untold man-hours and dollars. And yet for all its ills, C++ ranks near the top of the most useful (or at least used) languages ever explicitly designed (including Esperanto).

(4/11/08 - adapted from one of my comments in reddit.)

I should stress again that one of the more crucial issues surrounding language choice is the set of tools provided to us by the console vendors. C++ wasn't adopted until late in the console world because C++ standards weren't well supported by console vendors. Tools have always been poor on consoles compared to the PC (this has changed somewhat with the 360), and good quality C++ compilers were rare in previous console generations, but C compilers were available (athough they, too, came late - with the original PlayStation or Saturn, I believe?).

The PC gaming world hasn't seen this sort of lag. Game developers are eager to adopt new technologies. Other technologies have been unavailable on these platforms.

This is an exploratory post (as they all are..) and is subject to change.

18 comments:

kLL said...

Have you considered DigitalMars' D?

For me it has all the advantages of C++ (speed, flexibility and "abusability"), but has almost none of the drawbacks - e.g. it won't let you overrun arrays (but in debug compilation only - it doesn't penalize release version).

And the syntax is much much cleaner.

Anonymous said...

I find manipulating the language itself as a bug that just waiting to happen. If the language is not suited for your needs, then the choice of the language is wrong. It's just that simple.

Almost (except one) point you'v made, I can create on other general purpose languages such as Object Pascal (Delphi, Free Pascal etc), D and few other programming languages. I can also go down to use assembler level of code, and to go as high as many dynamic languages can provide me !

I believe that the reason people select C++ and C are because of myths rather then any other reason. If you'll actually look at C++, if you strip it from all the "patches" (technologies) that are not really part of the language itself, it can not do much, and there for it is very useless. The only reason people uses C++, is due to the patches, and the power it gives you.

Remember that hacks and tweaks for the languages are the source for many bugs, because all it takes is one developer that does not know/understand the tweak/hack to screw things up, not to mention bugs that simpler code that will not tweak/hack the language, will just not happen at all. This problem is so bad, that the assembler level of your C++ code in debug mode usually works differently then the non debug mode code, so there are many applications out there written in C++ with debug mode, because otherwise they have bugs that they just can not find or fix.

anonymous2 said...

(to anonymous): I think you cannot tell what language is better or worse, it depends of the kind of project, application, etc.

Look at the "about me", it said "I work at Electronic Arts (EA) developing technologies for games"
Ok, then, we have a game programmer (architect, or whatever), and then, he really needs the language to let him manipulate all kind of things, that other high level languages don't let you do (even if they let you, maybe the efficiency es not the same).

The message i trying to say, is, if you are doing an application web (IT maybe), then, use a language and tools for better productivity, but if you are a game programmer (of AAA games maybe), then look at efficiency, i want to see you doing a Call Of Duty 4 in Delphi.

The bugs are introduced by people, in all languages, if you have to rely on the language to not think about your bugs you are not a good programmer at all.

Simon said...

C++ good at linking and package management??? That's the most ridiculous thing I've heard all week. This is one of the weakest aspects of C++. Where to start:

* no standard ABI for compiled code. ("Don't mix compilers")

* no standard for managing namespaces and packages like in Java.

* Very hard to evolve a class and keep binary compatibility. Lots of obscure compiler depend rules need to be followed to do this. ("Change a .h file, rebuild everything that uses it")

* dynamically loading code modules has to be done manually. Java, Python and other languages load classes on demand.

* C++ code can call C code, but any other kind of mixed language development is a nightmare.

* easy to break features like dynamic_cast when loading share libraries. (My fun debugging adventure this last week...)

--
Simon

Anonymous said...

I think in the long run C++ will die.
Please dont get me wrong on that - programming languages rarely "die".
What I mean with die is that on a percentage level, people will choose different languages. Let me first start from the scripting world view:

For simple tasks, people used perl. But perl is a horrible mess, it gets a job done and then you discard the result. Enter ruby instead. It is beautiful.
Or enter python, it is a bit strict and not really perlish but you can write concise AND maintainable code in python.

Both languages are MUCH better than perl, and they are already pushing on the www (like php did, but php is hardly usable outside the web).

What do I want to emphasize here? On many areas where simplicity is needed, these scripting languages will dominate.

Now lets go to the business side.
We have java, but java has problems too. We have D, which needs to prove first. We have C#/NET which is the most direct threat to C++ and games.

It is true that C++ is an extremely powerful language, but at the same time it is needlessly complex. Some people may like this, but I just shrug indifferently and continue to use languages that dont give me headaches. (Oh I dont use Java by the way...)

Anonymous said...

Interesting post. I agree that the primary motivator for using C++ is speed. The note about C++ allowing for superior modular development than any dynamic language is either dead wrong or you aren't explaining yourself very well. Most modern language (even many Great Old Ones) have far superior package management and much cleaner, simpler mechanisms for module development.

ken said...

You may be right about C++ never dying (just like 6502 assembly never died, cough cough!), but your reasoning sounds exactly backwards.

C++ is inflexible, not flexible. For example, you have to declare every little detail before you've written it. Flexible languages, in comparison, may not require declarations at all, or may let you add them later (for speed) once you know what you want. That's not to say C++ is bad at what it does, but being flexible is not its forte; it's fast to run because it's insanely strict.

With sufficient effort, you can do anything in any (Turing-complete) language. In practice, though, this doesn't mean much, because nobody actually writes video games in C++ by Greenspunning themselves a CL, and C++ offers no syntactic abstraction so it's more often easier to just write things inline, using C++ idioms.

What makes C++ (and C) so widespread is the speed and size of its binaries, and (as you note) extreme path dependence.

Senzee said...

Ken,

It looks like we're talking about different types of flexibility.

The flexibility you describe is dynamic typing, which is more flexible than C++'s static typing but pushes a lot of bugs that can be caught at compile time (in a statically typed language) to run time, where it may be caught late or not at all - until it reaches the consumer. This can be one more terrible liability in large projects and is exactly the opposite direction that we would like to go. In addition, dynamic typing has a profound impact on performance.

However, C++ does offer generic types (templates) which can provide much (though not all) of the benefits of dynamic typing.

In pursuing a higher-level language, there is no doubt that we would want to pursue a statically (and strongly, as opposed to C++'s weak typing) typed language. For example, Java, C# or ML as opposed to Lisp. The more that can be caught at compile time, the better.

Senzee said...

Simon (and others),

You make excellent points about the package management of C++ and I'll probably have to back away from that argument. Java has a very elegant way of handling dynamic linking, but does not support static linking at all. And that it links each class individually at start up imposes a very significant runtime penalty.

I'd like to get some feedback from the community about package management strategies and what languages do what that works well.

Senzee said...

kll,

I don't know much about D, but I've heard only good things. I'll have to check it out.

Senzee said...

Looks like this made its way to reddit. And made for a very impassioned discussion about the virtues/drawbacks of C++.

http://reddit.com/r/programming/info/6fe7c/comments/

The reddit and digg crowd are quite different. Apparently, this is a pretty controversial topic on reddit.

notwithstanding said...

Here's the key: the interface between the abstraction of objects (as in object-oriented languages), and the abstraction of the "bare metal" (the abstract machine C represents) is not easy to manage. Each of the more successful languages has had a very different approach to doing so. C++ is as complex as it is because it is attempting to let you program on the bare metal and with objects in the same code. The result is that you have to worry both abouts bits and about object semantics at the same time. This is very very hard to wrap your head around completely and other languages have learned their lessons from it and adopted very different strategies for this interface. Java (and Python and Ruby and Lisp and ...) put up a firewall via a foreign function interface and obliges you to write the low-level stuff in a different language (typically C). C# allows low-level constructs directly but isolates them with a specific language feature (the "unsafe" keyword). Each of others weighs in on the object-oriented end and makes the machine-level less accessible than game programmers need. Conversely C doesn't give you enough high-level abstraction: everything, even such basic things as strings and hashtables needs to be hand-rolled. So even though C++'s solution is very difficult to learn properly (because it _doesn't_ provide a simple line between the two levels), it's still the language of choice for people who need to do low-level work down to the metal but also need a high-level abstraction most of the time.
I've been using C++ for fifteen years now in various capacities. And I'd say that the language that comes closest to being a sweet spot between the machine and objects is actually D, which has already been mentioned. I *strongly* recommend it as worth a look. I wasn't keen on learning a new language and got sucked in because when I read the description of D's features it was like reading a checklist of every one of the dozen things that drive me crazy in C++ fixed, methodically and thoroughly. It lets you use objects the 95% of the time and drop right down to the bare metal when you need to, but with a much, *much* cleaner interface between the two than C++ provides. (As a shining example you have a garbage collector -- which you can turn off for whatever portion of your program you find is too time-critical to afford GC.) This isn't surprising when you consider its origins, namely that of someone who has been writing C++ compilers for twenty years.

I strongly recommend spending some time with it.

James Iry said...

Tim Sweeny (of Unreal fame) gave a talk a few years ago called "The Next Mainstream Language" in which he discussed some ideals that a game developer might look for in a language. The slides and a bit of discussion are available online at http://lambda-the-ultimate.org/node/1277

In the talk he discusses things that are pretty foreign to the mainstream right now including dependent types, default immutability, algebraic data types, higher order functions, etc. It's very much worth a read whether you agree or not.

Anonymous said...

IMO lisp, and languages with similar macro flexibility simply top all other languages.
* Variables can *optionally* be specified to have a type.
* See no reason why lisp functions, with its variables fully specified would be any slower then C. Actually its probably (comparatively)trivial to actually convert these functions/structs to C.
* Even if fully specified functions are not at C's speed, one can use a foreign interface to C.

* Nearly any feature of other languages can be produced via a macro. (Although it would be made to fit a s-expression, but non-s-expressions are silly anyway.)

One thing I dislike about common lisp is that macros can only see their input, not what other macros can infer from then. It would, for instance be useful to see what data is attached to symbol at a certain point. Do not know if this is doable though.

As for c++, i remember that the compiler got all whiny when i tried to use the more advanced features.
And what is keeping the 'cond' from these other languages?! Wtf!

Anonymous said...

I hate the fact that in C/C++ asm syntax varies across compilers even for the same processor. This seriously sucks. I'm waiting for D to mature a lot more. The language itself seems to have nice potential but the compiler is pretty good but still a bit short when compared to C++ compilers. It just needs more time.

Yrb said...

Personally I don't think C++ is the best for language for performance. OCaml and good common lisp compilers can match or beat C++, and if it is well written seem to always very close.

I think C++'s performance is going to get even worse given the current development direction for cpu's. C++ doesn't exactly give the compiler much to work with.

I think it is getting less probable that a human can out tune a really good compiler for these architectures. Especially if the High level code is written in a function/declarative style, since this gives the compiler more information to do transforms.

We should concentrate on improving algorithms, and ways on declaring more assumptions to the compiler.

Check out Coconut as a way of programming high performance software, for one library it seems to be generating code for that is on average 4 times faster than hand tunned C, (SimdMath library for Cell BE).

See Video Here

The existing code always seems like a good argument, but I think that so much of it is going to be crippled going forward that is it going to be really worth it. Though I think that all those parts will be rewritten using new "improved" C++ in a piecemeal fashion.

It is worth switching to try and get rid of the decisions that were made for legacy reasons?

C++ used to be a good tradeoff, I don't think it is going forward, it certainly isn't getting any prettier as it gets older.

Mr Ed said...

This article is spot on. I miss C++ :(

Joshua Smith said...

Thank you for the nice links. It was easy to read, but I'd like to add that if your software company needs to be updated try software development service.