Hacker News new | ask | show | jobs
by noelwelsh 119 days ago
There are a few ways of looking at this:

- Purely on the JVM, you probably want ZGC (or Shenandoah) because latency is more important than throughput.

- On Erlang / the BEAM VM, each thread gets its own private heap, so GC is a per thread operation. If the request doesn't spill over the heap then GC would never need to run during a request handler and all memory could be reclaimed when the handler finishes.

- There can still be cases where a request handler allocates memory that is no solely owned by it. E.g. if it causes a new database connection to be allocated in a connection pool, that connection is not owned by the request handler and should not be deallocated when the handler finishes.

- The general idea you're getting at is often called "memory regions": you can point to a scope in the code and say "all the memory can be freed when this scope exits". In this case the scope is the request handler. It's the same idea behind arena or slab memory allocation. There are languages that can encode this, and do safe automatic memory management without GC. Rust is an obvious example, but I don't find it very ergonomic. I think the OxCaml [1] and Scala 3 [2] approaches are better.

[1]: https://oxcaml.org/documentation/stack-allocation/reference/

[2]: https://docs.scala-lang.org/scala3/reference/experimental/cc...

2 comments

See also arena allocation, for realtime systems. But those systems typically require that any task have a reasonably tight upper bound on memory usage.
Thank you, that’s what I came here to learn!