Memory management subsystem is one of the most important parts of operating systems.

It is very important to know about the abilities and limitations of memory manager.

In case of embedded systems with usually low memory, it is all the much more important.

For any memory requirements –

Determine if you enough memory to process data.

Get a section of memory from the available memory

Return a section of memory back to the pool of available memory so it can be used by other parts of program.

Memory Management

Why another memory management?

First of all pools are used to reduce the likelihood of programming errors.

For normal desktop environment any memory leak does not do much harm since programs do not run very long and when exiting, the operating system frees all memory anyway.

In a server environment or for embedded systems with limits on memory, even small memory leaks in a program parts that are repeatedly run can cause a server to crash.

With the pools concept, a developer registers any memory with the pool that has a predetermined lifetime.

Once the pool is destroyed, all resources managed by that pool are released automatically.

Mistakes within those are a lot easier to find.

Memory Allocation limitations

Limiting factors

When a process requests memory from operating system, various factors determine if the request will be successful or not.

Available Memory

The amount of physical storage space on the system allocated for memory.

OS Limits

The operating system has limits to the amount of memory that it can support.

Memory Fragmentation

Affects the size of contiguous memory blocks available to the process

Tradeoff decisions for an allocator

Speed of allocation

Speed of deallocation

Behavior in a threaded environment

Behavior when memory is close to filling

Cache locality

Bookkeeping memory overhead

Behavior in Virtual memory environments

Small or large objects

Real-time guarantees

Shortcomings of malloc()-based memory management

Managing memory with malloc() can be pretty daunting for programs that have long-running storage they need to keep around.

If you have lots of references to memory floating around, it is often difficult to know when it should be released.

Memory whose lifetime is limited to the current function is fairly easy to manage, but for memory that lives beyond that, it becomes much more difficult.

Memory Pools

What is Pool?

Pool allocation is memory allocation scheme that is very fast, but limited in its usage.

Memory pool are often used to override default malloc() behavior. Basic idea is that you allocate a larger pool of memory using malloc(), then use it to give memory to program in smaller pieces using preferred algorithm.

Memory pool doesn’t have strict definition, so there’s many different kind of pools used. One thing they have in common is that all the memory allocated from a specific pool can be immediately freed by freeing the pool itself.

Why should I use Pool?

Using Pools gives you more control over how memory is used in your program. For example, you could have a situation where you want to allocate a bunch of small objects at one point, and then reach a point in your program where none of them are needed any more. Using pool interface, you can choose to run their destructors of just drop them off into oblivion; the pool interface will guarantee that there are no system memory leaks.

When should I use Pool?

Pools are generally used when there is a lot of allocation and deallocation of small objects. Another common usage is the situation above, where many objects may be dropped out of memory.

In general, use Pools when you need a more efficient way to do unusual memory control.

Internal Structure

Internally, a pool is organized as a linked list of sub pools, block, processes and callback functions as shown in the figure.

Memory Pool vs Malloc

Memory pools allow memory allocation with constant execution time (no fragmentation). The memory release for thousands of objects in a pool is just one operation, not one by one if one uses malloc to allocate memory for each object. Third, memory pools can be grouped in hierarchical tree structures, which is suitable for special programming structures like loops and recursions. On the other hand, they need to be tuned for the application which deploys them.

Types of Memory Pool – Fixed size pools

A fixed size pool is a memory pool where the number of memory objects and size of each object is known and specified at the time of creation.

Allocating memory from a fixed pool is very fast and, more importantly deterministic. However the size of each allocation is fixed at the time pool is created.

Each memory object created in the fixed size memory pool would incur a fixed amount of overhead in terms of some housekeeping data.

Types of Memory Pool – Dynamic size pools

A dynamic size pool is a memory pool where the number of memory objects and size of each object is not known, only the size of memory pool is specified at the time of creation.

Dynamic pools provide essentially the same functionality as the system heap, so are rarely used.

In dynamic pools a region from memory is created for the module depending upon the size specified for creating. So, when a pool is created than the objects of different size say 56 bytes, 72 bytes … all can use the same memory pool.