5 ms·
It's quite common knowledge in the gamedev world (at least the part that writes C++ code, the other parts that uses C# or JS has roughly the same problem, just
by flohofwoe 2y ago
It's quite common knowledge in the gamedev world (at least the part that writes C++ code, the other parts that uses C# or JS has roughly the same problem, just caused by unpredictable GC behaviour).
Towards the end of the 90s, game development transitioned from C to C++, and was also infected by the almighty OOP brain virus. The result was often code which allocated each tiny object on the heap and managed object lifetime through smart pointers (often shared pointers for everything). Then deep into development after a million lines of code there's 'suddenly' thousands of tiny alloc/frees per frame and all over the codebase but hidden from view because the free happens implicitly via RAII - and I have to admit in shame that I was actively contributing to this code style in my youth before the quite obvious realization (supported by hard profiling data) that automatic memory management isn't free ;)
Also the infamous '25k allocs per keystroke' in Chrome because of sloppy std::string usage:
https://groups.google.com/a/chromium.org/g/chromium-dev/c/EUqoIz2iFU4/m/kPZ5ZK0K3gEJ https://groups.google.com/a/chromium.org/g/chromium-dev/c/EU...
Apart from performance, the other problem is debuggability. If you have a lot of 'memory allocation noise' to sift though in the memory debugger, it's hard to find the one allocation that causes problems.
- jpc0 2y ago> It's quite common knowledge in the gamedev world (at least the part that writes C++ code, the other parts that uses C# or JS has roughly the same problem, just caused by unpredictable GC behaviour). Isn't it pretty common in gamedev to use bump allocators in a pool purely because of this. Actually isn't that pretty common in a lot of performance critical code because it is significantly more efficient? I feel like RAII doesn't cause this, RAII solves resource leaks but if you turn off you brain you are still going to have the same issue in C. I mean how common is it in C to have a END: or FREE: or CLEANUP: label with a goto in a code path. That also is an allocation and a free in a scope just like you would have in C++...
- flohofwoe 2y ago> Isn't it pretty common in gamedev to use bump allocators Yes, but such allocators mostly only make sense when you can simply reset the entire allocator without having to call destruction or housekeeping code for each item, e.g RAII cleanup wouldn't help much for individual allocated items, at most to discard the entire allocator. But once you only have a few allocators instead of thousands of individual items to track, RAII isn't all that useful either since keeping track of a handful things is also trivial with manual memory management. I think it's mostly about RAII being so convenient that you stop thinking about memory management cost, garbage collectors have that exact same problem, they give you the illusion of a perfect memory system which you don't need to worry about. And then the cost slowly gets bigger and bigger until it can't be ignored anymore (e.g. I bet nobody on the Chrome team explicitly wanted a keystroke to make 25000 memory allocations, it just slowly grew under the hood unnoticed until somebody cared to look). Many codebases might never get to the point were automatic memory management becomes a problem, but when it becomes a problem then it's often too late to fix because that problem is smeared over the entire codebade.
- jpc0 2y agoNobody says that an object with memory allocated using a bump allocator can't use RAII for other uses. The destructor could even call delete on the pointer to the memory in the bump allocator and the bump allocator can happily implement delete as a noop or a tombstone operation of some sort. Now this does mean when you design your objects (see some talks on objects vs values for nuance there, oversimplified TLDR object exist in a place in memory but values are things that can be passed around) you need to make them aware of the allocator that allocated them. Values are generally stored in containers which the STL ones are allocator aware and you should be making your custom ones allocator aware too. Generally the expensive part of memory allocation isn't calling malloc, it's the underlying operations, when the underlying operation is +sizeof(T) and free is a noop you can happily keep using RAII and not care. CLARIFICATION: I'm saying having a T* member is an antipattern, make it std::unique_ptr with a custom deleter or it should be in a container, struct of arrays...
- flohofwoe 2y agoI don't think that self-destructing individual objects via 'smart-references' are a good idea, especially when you need to carry an allocator around (either in the object or in the smart-reference). Destruction should be explicitly performed at a specific time and place, and not happen decentralized in some random location of the code when a reference goes out of scope (I realize that this dismisses the whole idea of RAII and destructors and garbage collection in general, but ¯\_(ツ)_/¯).
- throwaway2037 2y agoI needed to Google about "bump allocators". I found this: https://stackoverflow.com/questions/62076569/is-this-implementation-of-malloc-a-bump-allocator https://stackoverflow.com/questions/62076569/is-this-impleme... > It's a really naive allocator that can be very fast due to the tiny amount of housekeeping involved, but you have to live with a pretty heavy constraint: there's no "free" operation for individual request - you just destroy the whole thing. To me, this sounds like an arena allocator. I remember seeing them in Apache SVN source code a squillion years ago. What's the big deal? For RAII, we can just do placement new in the ctor, and "arena free/delete" in dtor -- which might do nothing in practice. Also, was the original article focused on gamedev? I don't see any mention of it. For us normie programmers working on CRUD apps, we don't need bump/arena allocators. Ctor->new, RAII/Dtor->delete is just fine for us.
- jpc0 2y ago> Also, was the original article focused on gamedev? I don't see any mention of it. For us normie programmers working on CRUD apps, we don't need bump/arena allocators. Ctor->new, RAII/Dtor->delete is just fine for us. Yes arena allocators is the word I couldn't remember, a bump allocator is a way to implement an arena allocator and probably the most popular. Also I 100%, in general you shouldn't need an arena allocator, but if you are building a library you should be aware of allocators and make however you are allocating memory configurable so that if you do need to some day change it it doesn't involve a complete rewrite.
- pjmlp 2y agoAnd yet CryEngine, Unreal, and many others do just fine.
- panstromek 2y agoNot sure if you're joking or not, actually. Both of those are pretty well known for performance problems - especially in games from the mentioned era. When Crysis came out, it was notoriously laggy and the lag never really went away. Unreal lag is also super typical, I can sometimes guess if the game is using Unreal just based on that. This might have different causes, or game-specific ones, but the variability of it seems to match the non-deterministic nature of this kind of allocation scheme.
- pjmlp 2y agoAnd naturally every game influencer complaining about those engines has been able to prove that memory management was the issue of their complaints.
- panstromek 2y agoAs much as you were able to prove that CryEngine, Unreal, and many others do just fine.
- pjmlp 2y agoI have sales numbers, and market share adoption across the industry, proving that they do just fine, on my side. Whereas I am expecting profiler data showing memory issues caused by RAII patterns, from your side, or any of those influencers on whatever platform they complain about.
- panstromek 2y agoYea, because sales numbers are a measure of software performance and therefore Jira is the fastest software in the observable universe.