B_old
B_old

Reputation: 1291

Free memory with explicit size

I'm looking for malloc/free-like APIs in mainstream OSs that allow me to specify an explicit size during both allocation and de-allocation. What I hope to gain by this is that the runtime might spend less memory on bookkeeping when the allocated size is already available in the program.

On e.g. windows I only found free(), _aligned_free(), and _freea(), none of which take a second argument for size.

Upvotes: 6

Views: 385

Answers (3)

Wayne Taylor
Wayne Taylor

Reputation: 51

If you are looking for faster malloc & free, there is a new (13 Feb 2019) drop-in replacement for systems that already support a hardware memory manager unit, MMU. Most computers do, most micro-controllers don't.

There is a paper and a study that shows it reduces Firefox's memory by 16% and Redis by 39%.

It is called Mesh. Mesh dynamic memory allocation

Upvotes: 0

Useless
Useless

Reputation: 67713

I'm looking for malloc/free-like APIs in mainstream OSs that allow me to specify an explicit size during both allocation and de-allocation.

I'm not aware of any.

What I hope to gain by this, is that the runtime might spend less memory on bookkeeping, when the allocated size is already available in the program.

This idea certainly can work, but there are a couple of drawbacks:

  1. you have to partition allocation regions between objects whose allocated size is tracked by the caller, and objects where the allocator still needs to record that itself.

    This increases complexity and potentially memory fragmentation.

  2. you have to allocate exactly the size the program requests.

    That is, a normal allocator could decide to return a 96-byte chunk for a 64-byte request, because it's just been freed, is hot on cache, and splitting and re-coalescing chunks smaller than 64 bytes is not deemed worthwhile.

    Your allocator can't do that, in general (it is limited to rounding up to the next aligned chunk size).


Of course, there are plenty of specialized allocators that manage these tradeoffs explicitly.

Using or writing these is a perfectly normal thing to do when the general-purpose allocator isn't a good fit for your allocation patterns. But, they're generally not provided by the language or OS, because they're not general-purpose. They're provided by libraries (or by yourself).

Examples:

  1. You allocate and free a lot of objects with a previously-known fixed size.

    Write an object pool allocator for them. It doesn't need to track the allocation size, because it's always the same (often a template parameter). You don't need to explicitly track it in your code either, because it's implied by the type.

  2. Variable-sized allocations of trivial objects all with the same lifetime (eg, lots of char buffers).

    Write an arena allocator. It doesn't need to track individual allocation sizes, because you reset the entire allocator instead of freeing and re-allocating individual objects. You never explicitly delete the allocate objects, because they're trivial anyway.

NB. If you choose to integrate your allocator using new/delete overloads (and think it will benefit from the explicit size parameter) you absolutely can use the ones Maxim points out, with the following caveat:

... [explicit size overloads will be] Called instead of [the default overloads] if a user-defined replacement is provided, except that it's unspecified [which] is called when deleting objects of incomplete type and arrays of non-class and trivially-destructible class types.

Upvotes: 3

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136208

operator delete family does accept the size. See operator delete, operator delete[]:

void operator delete  (void* ptr, std::size_t sz) noexcept;
void operator delete[](void* ptr, std::size_t sz) noexcept;
void operator delete  (void* ptr, std::size_t sz, std::align_val_t al) noexcept;
void operator delete[](void* ptr, std::size_t sz, std::align_val_t al) noexcept;

Called instead of void operator delete(void* ptr) noexcept and void operator delete[](void* ptr) noexcept; if a user-defined replacement is provided.

With the benefit of the compiler providing the size for you.

Upvotes: 0

Related Questions