4 ms·
> I made a meshopt_Allocator class that could allocate large blocks of typed data and remember the allocated pointer; at the end of the scope all allocated bloc
by pjungwir 8y ago
> I made a meshopt_Allocator class that could allocate large blocks of typed data and remember the allocated pointer; at the end of the scope all allocated blocks would be deleted.
I only write occasional C, and no C++ since college, but I think this Arena pattern is drastically underused. I'd love to see it in web frameworks, where every allocation inside a request comes from the same place, and at the end you just give it all back. It seems like you could even offer that in Ruby. Does Rocket use anything like this? It seems like the kind of thing Rust folks would take advantage of.
Postgres memory allocation follows an Arena pattern, where you use palloc to grab memory, but you rarely have to free it, because it is all freed when the "context" completes. There are nested contexts for things like the connection, the transaction, the sql statement, a function call, etc., so as long as you're allocating from the right context, you can practically ignore cleaning up after yourself. (This is from the perspective of a frequent extension author but someone who has only barely contributed to the core project, so perhaps a more expert contributor can correct me and/or elaborate.)
EDIT: Btw, I really enjoyed the article; thank you for sharing your experiences with us!
- gmueckl 8y agoI recently introduced similar patterns in a few things I work on. The speedup I got over having to manage tons of small allocations surprised me a little.
- barrkel 8y agoA nicely tuned generational GC should end up with first and second generations effectively as arena allocators that get recycled very cheaply. When the time comes around to collect the second generation, it should have almost no live data, as it will only be filled with whatever was in flight across all the times the first generation was collected. When I understood this, it was an aha! moment for GC languages in stateless server contexts. I could see that for a properly written server - ideally keeping any long-lived mutable memory like caches off-heap - GC overhead could be negligible.
- anarazel 8y agoI'm very doubtful that's really true for databases. A lot of memory freed this way is not short lived. E.g. the contexts for running [parts of] an analytics query can both be large and quite long lived. And it's crucial that the memory is available again the instant the last query [part] finished, otherwise it's quite realistic to run out of memory. And adding latency by running through the many GB of otherwise used memory in hypothetical older generations isn't acceptable either.
- barrkel 8y agoI wrote stateless servers, if you missed that bit. Anything requiring large semi-long-lived intermediate buffers would need a different approach, I agree. Similar to caches; you don't want a mid-life crisis in a generational GC.