3 ms·
The article starts with: > This criticism is aimed at RAII — the language-defining feature of C++, which was wholesale imported to Rust as well. > bec
by throwaway2037 2y ago
The article starts with:
> This criticism is aimed at RAII — the language-defining feature of C++, which was wholesale imported to Rust as well.
> because allocating resources becomes easy, RAII encourages a sloppy attitude to resources
Then lists 4x bullet points about why it is bad.
I never once heard this criticism for RAII in C++. Am I missing something? Coming from C to C++, RAII was a godsend for me regarding resource clean-up.
- Hemospectrum 2y agoYou're most likely to hear it from kernel programmers and Go/Zig/Odin advocates, but it rarely comes up as a criticism of C++ in particular. Perhaps that's because RAII is merely "distasteful" in that cohort, whereas there are many other qualities of C++ that might be considered total showstoppers for adoption before matters of taste are ever on the table. There was an HN thread a few months ago[0] debating whether RAII is reason enough to disqualify Rust as a systems language, with some strong opinions in both directions. [0]: https://news.ycombinator.com/item?id=42291417 https://news.ycombinator.com/item?id=42291417
- SleepyMyroslav 2y agoThx for linked thread. It was an interesting read to me. I have got a feeling that the division comes from two different system programming folks. Hard realtime folks see unbounded time and uh-oh its fatal. On other side soft realtime folks ask about probabilities and profiling data and its relatively fine for them if probability is low enough. Where both of the camps would agree if number of effects is bound somehow.
- conradev 2y ago> Poor performance. Usually, it is significantly more efficient to allocate and free resources in batches. This one is big. It is a lot of accounting work to individually allocate and deallocate a lot of objects. The Zig approach is to force you to decide on and write all of your allocation and deallocation code, which I found leads to more performant code almost by default – Rust is explicitly leaving that on the table. C obviously works the same way, but doesn't have an arena allocator in the standard library. Re: C++ vs Rust, it might be more of a pain in Rust because of this: https://news.ycombinator.com/item?id=33637092 https://news.ycombinator.com/item?id=33637092
- ladyanita22 2y agoI am happy that Rust defaults to the easier, saner, safer approach by default, but lets you bypass RAII if you want to do so.
- conradev 2y agoYeah, I agree. It makes sense and I'm glad that Drop is in no way guaranteed. I am excited for allocator-api to eventually stabilize, too!
- flohofwoe 2y agoIt'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.
- XorNot 2y agoThe "hard mode" described in this article covers an issue I do keep running into with Golang funnily enough: I really hate the global imports, and I really want to just use dependency injection for things like OS-level syscalls...which is really what's happening here largely. So it's interesting to see something very similar crop up here in a different language and domain: throw a true barrier down on when and how your code can request resources, as an explicit acknowledgement that the usage of them is a significant thing.
- GuB-42 2y agoIn language performance benchmarks, you often see C++ being slower than C. Well, that's a big part of the reason. There is no real reason for C++ to be slower since you can just write C code in C++, with maybe a few details like "restrict" that are not even used that much. The big reason is that RAII encourage fine grained resource allocation and deallocaion, while explicit malloc() and free() will encourage batch allocation and deallocation, in-place modification, and reuse of previously allocated buffers, which are more efficient. The part about "out of memory" situations is usually not of concern on a PC, memory is plentiful and the OS will manage the situation for you, which may include killing the process in a way you can't do much about. But on embedded systems, it matters. Often, you won't hear these criticisms. C programmers are not the most vocal about programming languages, the opposite of Rust programmers I would say. I guess that's a cultural thing, with C being simple and stable. C++ programmers are more vocal, but most are happy about RAII, so they won't complain, I can see game developers as an exception though.
- throwaway2037 2y ago> In language performance benchmarks, you often see C++ being slower than C. This is the first that I have ever seen such a statement. And, I am sure we could legitimately write exactly the opposite: <<you often see C being slower than C++>>. Not much being said here. As I understand, C++ template code can be much faster than equivalent code in C because the compiler has more metadata for optimisation. The classic case is C's qsort() vs C++'s sort(), where the C++ version is much faster due to compiler optimisation.