Re:Zig, parser combinators, and why they're awesome
by logicchains on Thursday March 11, 2021 @07:05AM
(#26423137)
For ultra-low-latency programming, you generally want to avoid dynamic memory allocation on the hot path. Instead it's common to use a slab allocator, from memory on the stack or that was dynamically allocated on startup, to continuously reuse the same memory. E.g. when a web request comes in, allocate all temporary per-request state from a single bump allocator, then after the request has finished just "free" everything by setting the "allocateFromHereNext" pointer back to the start of the allocator's buffer. This is not only the fastest means of allocation/deallocation (just bump a pointer), but also means that new requests can reuse the same memory addresses (the allocator's internal buffer), achieving better cache locality as the memory's already in cache.
Zig is ideal for this as all stdlib functions that allocate take an allocator as a parameter (so there's no hidden allocation), and the stdlib provides a bunch of allocators. This is even better than C++, where some functions like std::stable_sort unavoidably allocate memory. Rust doesn't have much support for custom allocators in the stdlib although it's being worked on, but it's more difficult to implement in Rust as the compiler must be able to ensure that the allocator (or at least its buffer) outlives all the things being allocated from it.
Zig is ideal for this as all stdlib functions that allocate take an allocator as a parameter (so there's no hidden allocation), and the stdlib provides a bunch of allocators. This is even better than C++, where some functions like std::stable_sort unavoidably allocate memory. Rust doesn't have much support for custom allocators in the stdlib although it's being worked on, but it's more difficult to implement in Rust as the compiler must be able to ensure that the allocator (or at least its buffer) outlives all the things being allocated from it.