-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Add general purpose allocator(s) to standard library #480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Nice write up! I've been thinking about allocators a little bit lately as well and the current API in zig so I might write down my thoughts here as well. The current allocator interface is restricted to using memory from global state (i.e. from the os or a pre-allocated array as in the debug allocator). If we had a vtable abstraction (see #130) we could extend the types of allocators that could use the same interface. All the following assumes we have a vtable abstraction. For example, consider a fixed stack allocator which could be useful for a memory limited embedded system. In the current zig we would need to make the array global and set up a unique allocator across the program. With an interface-like abstraction we could generate types of allocators which fit our requirements locally.
A fixed allocator like this would make zig much more suitable for embedded work as having to resort to global memory for allocations is not always wanted. This could also be used to implement stack-backed up-front memory allocators with pre-defined limits easily too.
Getting back to you, I think we can incorporate a lot of these more complex ideas to dedicated allocators as long as we can generate the implementations easily. Response
I think we can possibly follow this example. Since allocators in zig are generally not global (excluding external ones from c) we should always be able to instead store the metadata in some local state instead. In the case that an allocator does use global state (i.e. is a malloc wrapper) then we can just ignore the parameter (pass 0).
That's interesting, although i suspect that depending on the type of allocator it could become substantially more useful. Falling back to the default
All useful tools. I wonder how far we could get with wrapping existing base allocator functions and injecting wrapper code to perform the require task. For example:
We could expose functions which return modified allocators with the appropriate limits applied. Limiting an allocator would be as easy as calling EndThis was a bit of a tangent. I do like a lot of the things you mentioned and would like to keep them in mind. I do really think that some vtable abstraction would make most of these things much easier to use from a user perspective. |
My allocator is very complex, it took several iterations, some features were eventually even dropped as not worthy the complexity. I do not suggest to adopt it, just point what may happen. Some people like to start project from a clean sheet. I suspect that among those who try completely new language this number is significant. It would be handy to have mechanisms which allow existing libraries stay usable even in such situation, when someone decides to reimplement basic functionality like the allocator. (Negative example here is C++ which married to stateless STL allocator concept, and if someone wants to change it he needs to rewrite whole STL, like EA had to.) I have few half baked ideas, like ability to say "use this code if it compiles": |
I just want to say thank you @PavelVozenilek for all these use cases. Zig thrives on use cases. We might say "no" to certain features but we have a responsibility to have a reasonable solution for any valid use case. |
@bscheinman there are some interesting tidbits here for your information if you're working on that general purpose memory allocator. |
Possibly of interest? https://github.com/microsoft/mimalloc |
Looking into https://github.com/zig-lang/zig/blob/master/std/mem.zig I decided to describe my own allocator implementation for a C project. I am not proposing anything here, just would like to point out that projects do strange things and language/stdlib should not restrict them.
I decided to avoid the global allocator (malloc/free) and implement my own variant, something what would strongly protect against bugs.
I implemented three allocator variants:
Allocator API (implemented with function pointers) had following features:
Every allocator had choice to automatically drop all still allocated data when the allocator itself was destroyed. The other option was to report unfreed data. This reduced the need to implement and invoke destructor-like functionality everywhere.
Allocated blocks were protected in DEBUG mode:
Other features:
Implementation of all this was large, 10k - 20k of lines of code (with tests). But it was probably worth the effort, saving days of frustrated chasing of memory bugs.
The text was updated successfully, but these errors were encountered: