Except back when I was studying, because it was textbook stuff, I have rarely implemented those with a lot of small (thus very fragmented) allocations linked with pointers. Even with good allocators, it eventually tends to fragment memory a lot and have bad locality properties, which is pretty bad for caches.
True, that's why I said it was just the
simplest implementation.
Memory allocation strategies themselves are a very complex topic, especially when you move from a single continuous heap (C
sbrk() style) to obtaining and returning arbitrary pages back to the OS (POSIX C anonymous
mmap() style). For pooled allocators, the discontinuous/page approach is not only easier, but when entire pools are discarded, the memory used can immediately be returned to the kernel, too; and fragmentation is much easier to avoid.
The main benefit of pooled allocators is that it makes it easier to write code that does not leak memory, because the developer does not need to track each individual allocation, and can instead treat them as
sets. Using a new
set for each complex task means the programmer only needs to remember to discard the
set, not each and every allocation individually.
I usually allocate largish chunks of memory and handle objects in it with indexing. In many cases, this is quite effective and the resulting performance is often very largely better. This is a form of pooling.
Yes, and that is exactly how and why Python NumPy implements its own array type, for example. I myself also use this in C a lot; so often that I no longer even think about it. (I worry more about the names of the variables/members; I like to use
used for the number of elements currently in use, and
size for the number of elements allocated for the area, with often
data as the pointer to the area.. it soothes my OCD, I guess, but some people have found such names unintuitive.)
When I wrote above "the locality of the allocations is not important at all", I tried to express that I am not talking about that form of pooling – which is common, but done on the "user" or "application side", with the application developer managing the pool –, but having dynamic memory management where each allocation always belongs to a pool. For example, in C, you'd have
malloc(pool, size),
calloc(pool, size, count),
free_all(pool),
new_pool(parent_pool), and so on. (Logically, the
NULL pool, the default pool, would usually have the same lifetime as the process.)
I did not mean that data locality isn't important in general. It is, for efficiency and other reasons. I just wanted to try and highlight the usefulness of the other aspects of pooled memory management.
(SiliconWizard, I do believe you know perfectly well all I wrote in this post already; I only wrote this in the hopes that it helps others understand this too.)