Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Almost every AAA game I've seen didn't use the STL. Boost is a definite no-go for most studios.

Stack allocations are discouraged because they can introduce non-deterministic bugs (stack overflow depending on the call sequence which can't be predicted in advance).

Its nearly impossible to write a game without dynamic allocations. Most of the time they'll override the new/delete operators and on that level they work almost exclusively on void*.

You're working on a scale where a lot of the C++ features work against you.



- "Almost every AAA game I've seen didn't use the STL."

that’s probably because most of the AAA games you've seen used old in-house libraries that replaced the STL, since the earlier STL implementations weren't the best.

STL is not 100% the way to go every time, but i would say that nowadays unless there’s a really specific implementation need, it should be used at least 90% of the times, even if only for base for new data structures to be built on top of.

- "Stack allocations are discouraged because they can introduce non-deterministic bugs (stack overflow depending on the call sequence which can't be predicted in advance)."

i really don’t understand this problem, you can change the stack size on every compiler and every OS either on compile time or runtime. also, are you writing functions or methods with 10k LoC?

stack allocations are actually easier to follow than heap, its not even close..

- "Its nearly impossible to write a game without dynamic allocations. Most of the time they'll override the new/delete operators"

yes i agree, dynamic allocations are still really needed, and not only for games.

But, overriding new / delete operators in C++ when you can set custom allocators and deallocators for both unique_ptr and shared_ptr? once again i think that’s more of a legacy code update problem than an actually implementation need problem.

- "and on that level they work almost exclusively on void*."

only if they want to, that’s what templates (and again the STL) are here for.

I’m not saying pure C++11/14 features are the only way to go, i just think that at least in new code it should take priority, the cleanness and robustness it provides its just too good to ignore.


You arguably don't need that many data structures in a game engine, almost everything is tightly packed in linear arrays. Even hash-maps are frowned upon. The single most used structure I've seen in engines is the plain old array because of cache locality. Everything is pre-sorted, pre-looked-up and pre-crunched so the main use-case is a straightforward linear traversal with as little branches as possible. Also templates can greatly affect compilation times which are already horrible on projects of such magnitude.

On the last AAA game I worked on we had very tight memory constraints and running about a dozen threads. Almost all of them used the minimum stack size except for the main thread. There were still a lot of stack allocations, but only for very small temporary objects and when the call stack was known to be shallow. Using megabytes for stack sizes would consume a noticeable percentage of the available memory which was direly needed elsewhere.

I've seen one game using shared_ptr and it was far from being great. There's a big overhead to it when compared to custom allocators. You can't easily optimize for cache locality with shared_ptr (as far as I know!) and working around enable_shared_from_this can be a real pain. With custom allocators you can easily optimize according to the use-cases.

Finally, templates are required to know their type at compile time, which for things like allocators is just not possible in many cases. For example, we used a bump-the-pointer allocator for a frame's temporary values which could be of any type but still needed cache locality. We also used a fixed-size allocator when avoiding memory fragmentation was more important than cache locality. Both would be impossible to do on anything but void*.


Ah man, fond memories of game dev. That's the way you write high performance C/C++.

I haven't taken the time to dig into seeing how these techniques will translate to Rust(obviously unsafe).


I haven't tried Rust yet, but they all easily translate into D!

I've lost count of the number of times I've thought to myself "I wish C++ has this D feature." A lot of them are being added now but the interesting ones (concepts!) are still years away and some (inout functions!) are nowhere in sight.

And then there's templates, mixins, auto this, compile-time reflection, and so much more. Its far from perfect (nothing is) but constantly improving and rather productive. Of course also being a user of Clojure (and Emacs-LISP) I sometimes miss something like defmacro, which I can almost get with mixins and templates but often not as elegantly. On the other hand, I write shell scripts in D all the time and not in Clojure!


Did they ever fix the memory release semantics with std::vector?

Last time I looked std::vector::clear() wasn't required to release memory and caused a lot of headache when certain implementations wouldn't free the underlying memory.

I'm aware that the work around is to assign a new std::vector<T>() but that always felt like more of a hack then anything else.


this is a reply to vvanders comment, for some reason i cant reply directly to his comment, so ill reply to myself..

they didn’t really "fix" it, instead they added a method called std::vector<T>::shrink_to_fit() which i'll admit its not the most elegant way, but it works.

what it does is, it resizes the capacity() to be the same as the size(), deallocating all the extra memory.


About the reply issue: its simply HN's mechanism to prevent flamewars from escalading quickly. The deeper a comment is the longer you have to wait after it is posted to be able to reply to it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: