What are the advantages and disadvantage of using jemalloc vs malloc vs calloc and other common alternatives?

2.9k views Asked by At

Reading the Rust subreddit today I came across comments that:

jemalloc is optimized for (multithreaded) speed, not memory usage

After doing more research I found that there are even more alternatives (such as calloc).

I would like to understand what the advantages and disadvantages of the different memory allocators?

If this question seems silly, my background is mainly interpreted languages (which don't expose such fine grain memory control).

1

There are 1 answers

1
Ameen On

malloc, calloc, and realloc

These functions are not different allocators. They are different ways of asking for memory from the same allocator.

  • malloc provides memory without initializing it (filled with whatever the previous user stored in it).

  • calloc is same as malloc but it will also initialize the memory (fill it with the zero byte 0x00).

  • realloc takes an already allocated memory and allows the users to resize it.

So, in the context of allocators and their different implementations, malloc, calloc and realloc are not listed independently, because each allocator implementation needs its own version of these functions.

jemalloc, ptmalloc, ...

When someone wants to implement a different allocator, he can't (can but shouldn't by default) name it malloc because it will collide with the C standard library one. Instead, they usually give it a different prefix like jemalloc, ptmalloc, nedmalloc, tcmalloc and others.

It is worth mentioning that there are, also, multiple implementations of the C standard library itself and each will implement its allocator differently. So malloc will have a different implementation based on what standard library being used when compiling the code. Examples are: the GNU C Standard library, MSVC standard library, etc.

What is the difference between different allocators?

To know the exact advantages and disadvantages of each implementation, one must read the documentation written by the author/authors of each one if it exists, read the code to understand the algorithm or read articles/research papers written by experts that talks about that particular implementation.

However, if I were to categorize the differences between these implementations, I would list the following:

  1. Some implementations focus on certain usage patterns and try to optimize for them even at expense of decreasing efficiency of other cases. An example for this would be jemalloc where they focused on optimizing allocation from multiple threads to make it faster but at the expense of using more memory. These types of allocators typically deployed upon careful investigation of a specific case that showed it will benefits from this trade-off.
  2. Some implementations put a certain limitation on the usage of the allocator in order to make it faster. An example is single-threaded allocators which will eliminate the need for synchronization objects to make it faster.
  3. Other implementations try to be as general-purpose as possible and doesn't favor any case over the others. This category includes the default allocators that is included in the standard libraries.