I have a memory pool class that manages memory objects of fixed sizes, a bit like a primitive malloc()
that can only return memory blocks of a few predefined sizes and unlike malloc()
is guaranteed to always be O(1), which makes it suitable for time critical code.
To prevent that the pool consumes too much memory, the creator can place an upper bound on the pool. And this bound arises an interesting question:
For memory management purposes every memory block must have a header that consumes some memory as well. How much is system dependent, e.g. it depends on how big pointers are, and thus is not easy to predict for unknown target platforms. Also the header is always equally large, no matter how big the memory block is, so the relative overhead varies as well and becomes the bigger the smaller the block is; that means the total overhead at runtime is also hard to predict even if the exact header size is known as it depends on how many blocks of which size will be in use, which may not even be known in advance in many cases.
The question is, should the overhead count towards the upper bound of the pool or not?
What speaks for counting it is that the bound will be absolute. If I set the bound to 512 kiB, I know for sure that no matter what I will do later on in my code, this pool will never use more than 512 kiB of memory. This is very useful on systems with very limited resources, as I can sum up all my pools and know for sure the worst case memory consumption to expect.
What speaks against it is that I won't know how much usable memory I will get out of the pool as that depends on the size of an unknown header (the header is private) and on the overhead, which depends on the size of the blocks I will request at runtime. If the bound just counts the usable memory, I will know that I can get 512 kiB of memory blocks out of that pool and thus can store 512 kiB of data in memory for sure. What I won't know is how much the total memory consumption will be in case I use all of the 512 kiB, as it will even vary depending on how many small and how many big blocks I have requested.
Programmatically its easy to implement the pool either way so it boils down to what behavior I desire and I see good reasons for either way. And yes, I could even implement the pool in such a way, that even this can be selected during creation but I don't think that this would be a good idea. The class should behave one way or the other way but it should always behave the same way, everything else will only cause confusion IMHO and lead to subtle bugs.