LmCast :: Stay tuned in

Comparison of Malloc() Algorithms

Recorded: Sept. 17, 2026, 6 a.m.

Original Summarized

Comparison of Arena Architecture in malloc() | Egbert Blog

Egbert Network

Motto

Articles

Categories

Tags

Archives

Uses

About

Jan 20 2026

Comparison of Arena Architecture in malloc()

Memory Allocation
Problems
Limit Memory Allocation (if not necessary)
Multithreaded programs often do not scale because the heap is a
bottleneck.
When multiple threads simultaneously allocate or deallocate memory from
the allocator, the allocator will serialize them. Programs making
intensive use of the allocator actually slow down as the number of
processors increases.
Malloc (libc) is the worst memory allocation API to use.
Programs should avoid, if possible, allocating/deallocating memory too
often and in particular whenever a packet is received.
In the Linux kernel there are available kernel/driver patches for
recycling skbuff (kernel memory used to store incoming/outgoing
packets).
Using PF_RING (into the driver) for copying packets from the NIC to the
circular buffer without any memory allocation increases the capture
performance (around 10%) and reduces congestion issues.
Design Evolution
Basic design of malloc() is to dynamically pre-allocate a pool of memory
from the OS in which applications can then take smaller pieces from.
malloc() is a standard API having a choice of different allocation
algorithms and to mitigate the expensive OS system calls (typically done
at program initialization time) during allocation of its system memory.
The first memory allocation scheme started with a stack-based memory
allocation.
Next came the dynamic-based memory allocation scheme where linked-list
and bucket-heap mechanism are used to divide the private-heap using size
class approach.
Soon, garbage collection algorithm introduced the initial backend of the
memory allocation scheme. Frontend covers the usual malloc() API, et
al.
In 2006, a third pool was introduced (after operating system memory pool
and library-based memory pool) called the “arena”. Arena is a
jemalloc-term and is intended to deal with different memory types such
as different-speed memory bank or NUMA-architecture, as well as memory
tied to specific to each of the multiple CPU core or even CPU infinity.
Frontend Evolution
Frontend manages the memory being given to the application.
Within the frontend of the memory allocation system, the evolution went
in the following order:

link-list free space
heap-bucket size classes (eliminating an object header)
(Process) Owner encoding
single core local allocation buffers (CLABs)
Epoch encoding
Large-size class memory block by direct mmap()
Hazard pointers (safe memory reclamation for lock-free objects) (M.M. Michael, 2004)
Arena memory pool (CPU/core and thread, separately)
thread-specific local allocation buffers (TLABs)
constant-time modulo synchronization (early return to OS pool, or FreeBSD madvise call)

Backend Evolution
Backend of the memory allocation system manages the empty, straggling,
fragmented or no-longer used memory blocks back to the OS (thereby
reducing RSS).

Pool semantic: Remote f-list encoding, using Treiber stack), (R.K. Treiber, 1986)
buddy algorithm
binary buddy algorithm
BIPOP Table (span-based allocator)(S. Schneider, 2006) aka local free list and remote free list
segment queue (Quasi-linearizability, Y. Afek, 2010)
multi-core distributed queue (A. Haas, 2013)
k-FIFO queue (T.A. Henzinger, 2013)

Competition
There are better ones out there that does not worsen as more threads/processes performs memory allocation system calls; they are listed in best-to-good performance order [seed with source]:
Comparison of malloc design

Allocator
Origin / Maintainer
Thread Safe
Per-Thread Cache
Multi-Arena / Heaps
Lock-Free Fast Path
NUMA Aware
Fragmentation Control
Notes

dlmalloc
Doug Lea
No
No
No
No
Low
Single global heap; basis for many later allocators

ptmalloc2 / ptmalloc3
glibc
Yes
Limited
Yes
No
Medium
glibc default; arena locks cause contention

glibc malloc (current)
GNU
Yes
Limited
Yes
No
Medium
Wrapper around ptmalloc with tunables

jemalloc
FreeBSD / Meta
Yes
Yes
Yes
Partial
High
Thread-arena affinity reduces CAS contention

tcmalloc
Google
Yes
Yes
Yes
Partial
Medium-High
Per-CPU caches; central freelists still exist

mimalloc
Microsoft
Yes
Yes
Yes
Yes
High
Designed to minimize atomic ops and false sharing

Hoard
Emery Berger
Yes
Yes
Yes
Partial
Medium
Focus on scalability and false-sharing avoidance

nedmalloc
NEDMALLOC
Yes
Yes
Yes
No
Medium
dlmalloc-derived with thread caching

phkmalloc
FreeBSD
Yes
Yes
Yes
No
Medium
Early FreeBSD allocator family

libumem
Solaris
Yes
Yes
Yes
Yes
Medium-High
Solaris allocator with debugging and locality support

mtmalloc
Solaris
Yes
Yes
Yes
Yes
Medium
Solaris multithreaded allocator

snmalloc
Microsoft Research
Yes
Yes
Yes
Yes
High
NUMA-aware
security- and scalability-focused

lockless malloc (research)
Academic / Experimental
Varies
Yes
Varies
Yes
Low
Often CAS-heavy; not production ready

ltalloc
Academic

CAS, Atomic Contention Characteristics
CAS / Atomic Contention characteristics

Allocator
Estimated Atomics per alloc/free
Shared Cacheline Risk
CAS Contention Sensitivity
Notes

dlmalloc
High
High
Very High
Global structures and locks dominate

ptmalloc2 / ptmalloc3
Medium-High
High
High
Arena locks cause cacheline bouncing

glibc malloc (current)
Medium-High
High
High
Wrapper around ptmalloc

jemalloc
Low
Low
Low
Arena-local metadata; minimal shared CAS

tcmalloc
Low-Medium
Medium
Medium
Per-CPU caches; central freelist CAS

mimalloc
Very Low
Very Low
Very Low
Designed to minimize atomic ops

Hoard
Medium
Medium
Medium
Reduces false sharing but still synchronized

nedmalloc
Medium
Medium
Medium
Thread caches reduce but don’t eliminate CAS

phkmalloc
Medium
Medium
Medium
Older FreeBSD design

libumem
Low
Low
Low
Lock-free fast paths on Solaris

mtmalloc
Low
Low
Low
Per-thread structures reduce atomic sharing

snmalloc
Very Low
Very Low
Very Low
Message-passing model avoids shared CAS

lockless malloc (research)
High
High
High
Often CAS-heavy despite no locks

NUMA, Memory Locality characteristics
NUMA / Memory Locality characteristics

Allocator
Explicit NUMA Support
First-Touch Friendly
Cross-NUMA Traffic Risk
Locality Preservation
Notes

dlmalloc
No
Yes
Very High
Poor
Single heap across nodes

ptmalloc2 / ptmalloc3
No
Partial
High
Fair
Arenas not NUMA-bound

glibc malloc (current)
No
Partial
High
Fair
Relies on OS placement

jemalloc
Partial
Yes
Medium
Good
Optional NUMA arena tuning

tcmalloc
Limited
Yes
Medium
Fair
CPU caches not NUMA-aware

mimalloc
No
Yes
Low
Very Good
Strong thread locality

Hoard
No
Yes
Medium
Good
Per-processor heaps help

nedmalloc
No
Yes
Medium
Fair
Thread caches but global fallback

phkmalloc
Partial
Yes
Medium
Fair
Early locality optimizations

libumem
Yes
Yes
Low
Very Good
Solaris NUMA policies

mtmalloc
Yes
Yes
Low
Very Good
Designed for NUMA Solaris systems

snmalloc
Yes
Yes
Very Low
Excellent
NUMA-first architecture

lockless malloc (research)
No
Varies
High
Poor
Locality rarely addressed

Benchmark-Oriented Practical Performance
Benchmark-Oriented Practical Performance

Allocator
Small Alloc Throughput
Large Alloc Throughput
Latency Under Contention
Memory Overhead
Fragmentation Risk
Notes

dlmalloc
Low
Medium
Poor
Low
High
Not suitable for multithreaded loads

ptmalloc2 / ptmalloc3
Medium
Medium
Poor
Medium
Medium
glibc default

glibc malloc (current)
Medium
Medium
Poor
Medium
Medium
Tunable but limited

jemalloc
High
High
Very Good
Medium-Low
Low
Excellent all-around allocator

tcmalloc
Very High
Medium
Good
Medium
Medium
Optimized for small objects

mimalloc
High
High
Excellent
Low
Low
Great latency predictability

Hoard
Medium
Medium
Good
Medium
Low
Designed for scalability

nedmalloc
Medium
Medium
Fair
Medium
Medium
Older but usable

phkmalloc
Medium
Medium
Fair
Medium
Medium
Historical FreeBSD allocator

libumem
High
Medium
Very Good
Medium
Low
Strong debugging support

mtmalloc
High
Medium
Very Good
Medium
Low
Enterprise Solaris workloads

snmalloc
High
High
Excellent
Low
Very Low
Security + scalability focus

lockless malloc (research)
Varies
Varies
Poor
Low
High
Often unstable in practice

Allocator Recommendation
Allocator Recommendation

Workload Type
Primary Bottleneck
Key Risks
Recommended Allocator
Why It Fits
Alternatives
Avoid

Highly Contended Multithreaded
Atomic/CAS latency
Cacheline bouncing
jemalloc
Multi-arena + thread affinity minimizes shared CAS
mimalloc
snmalloc,dlmalloc ptmalloc

Low-Latency / Tail-Sensitive
Allocation jitter
Lock convoying
mimalloc
Very low atomic count and predictable fast paths
snmalloc
jemalloc,tcmalloc

NUMA / Multi-Socket Servers
Cross-node memory access
Remote cache ownership
snmalloc
Explicit NUMA awareness and locality control
jemalloc (NUMA tuned)
libumem,glibc malloc

Small Object Heavy (RPC / Web)
Allocator throughput
Central freelist contention
tcmalloc
Per-CPU caches optimized for small allocs
jemalloc
mimalloc,ptmalloc

Large Object / Mixed Sizes
Fragmentation
TLB pressure
jemalloc
Excellent fragmentation control and extent management
mimalloc
glibc malloc

False-Sharing Sensitive
Cacheline ping-pong
Metadata sharing
Hoard
Designed to avoid false sharing
jemalloc
mimalloc,dlmalloc

Security-Hardened
Use-after-free exploits
Heap corruption
snmalloc
Isolation + security invariants
mimalloc (secure)
ptmalloc

Debugging / Leak Detection
Memory misuse visibility
Silent corruption
libumem
Strong runtime diagnostics
jemalloc (profiling)
tcmalloc

Embedded / Low Memory
Footprint size
Overhead
dlmalloc
Small and simple if single-threaded
nedmalloc
jemalloc

Real-Time / Deterministic
Unbounded latency
OS interference
mimalloc
Low variance fast paths
snmalloc
jemalloc,tcmalloc

HPC / Scientific NUMA
Memory bandwidth
Remote NUMA hits
snmalloc
NUMA-first design and low CAS traffic
jemalloc + mbind
glibc malloc

Legacy / Compatibility
ABI stability
Toolchain issues
glibc malloc
System default and safest fallback
ptmalloc

Decision Chart for Malloc Selection

Graphviz DOT file

[http://www.phrack.org/issues.html?issue=57&id=8#article]
[https://sploitfun.wordpress.com/2015/03/04/heap-overflow-using-malloc-maleficarum/]
[http://phrack.org/issues/66/10.html]

References

R. J. Maher, Problems of storage allocation in a multiprocessor multiprogrammed system, Communications of the ACM, 4(10):421-422, October 1961

A fast storage allocator, Kenneth C. Knowlton, Communications of the ACM, 8(10):623-625, October 1965.

Statistical properties of the buddy system, P.W. Purdom and S. M. Stigler, Journal of the ACM, 17(4):683-697, October 1970

Statistical investigation of three storage allocation algorithms, P. W. Purdom, S. M. Stigler, and Tat-Ong Cheam, BIT, 11:187-195, 1971.
A note on an optimal-fit method for dynamic allocation of storage, J. A. Campbell, Computer Journal, 14(1):7-9, February 1971.
Worst-case analysis of memory allocation algorithms, M. R. Garey, R. L. Graham, and J. D. Ullman, In Fourth Annual ACM Symposium on the Theory of Computing, 1972
A class of dynamic memory allocation algorithms, D. S. Hirschberg, Communications of the ACM, 16(10):615-618, October 1973
Dynamic storage allocations of arbitrary sized segments, J. S. Fenton and D. W. Payne, In Proc. IFIPS, pages 344-348, 1974
Worst-case of Memory Allocation Algorithms, Garey 1972
A simplified recombination scheme for the Fibonacci buddy system, B. Cranston and R. Thomas, Communications of the ACM, 18(6):331-332, July 1975.
Buddy systems, J. L. Peterson and T. A. Norman, Communications of the ACM, 20(6):421-431, June 1977.
Worst case fragmentation of first fit and best fit storage allocation strategies, J. M. Robson, Computer Journal, 20(3):242-244, August 1977.
Fast-fit: A new hierarchical dynamic storage allocation technique, M. Tadman, Master’s thesis, UC Irvine, Computer Science Dept., 1978.

The double buddy-system, David S. Wise, Technical Report 79, Computer Science Department, Indiana University, Bloomington, Indiana, December 1978

Memory fragmentation in buddy methods for dynamic storage allocation, A. G. Bromley, Acta Informatica, 14(2):107-117, August 1980.

Optimal fit of arbitrary sized segments, Ivor P. Page, Computer Journal, 25(1), January 1982.
Parallelizing the usual buddy algorithm, A. Gottlieb and J. Wilson, Technical Report System Software Note 37, Courant Institute, New York University, 1982.
Fast fits: New methods for dynamic storage allocation, C. J. Stephenson, In Proceedings of the Ninth Symposium on Operating Systems Principles, pages 30-32, Bretton Woods, New Hampshire, October 1983. ACM Press. Published as Operating Systems Review 17(5), October 1983.
On the asymptotic optimality of first-fit storage allocation, E. G. Coffman, Jr., T. T. Kadota, and L. A. Shepp, IEEE Transactions on Software Engineering, SE-11(2):235-239, February 1985.
Efficient implementation of the first-fit strategy for dynamic storage alloca-
tion, R. Brent, ACM Transactions on Programming Languages and Systems, July 1989.
Fast allocation and deallocation of memory based on object lifetimes, David R. Hanson, Software Practice and Experience, 20(1), January 1990.
Dynamic Storage Allocation: A Survey and Critical Review, very useful chronological order of malloc(), 1995

The Memory Fragmentation Problem: Solved? Johnstone 1997

A Memory Allocator, 2000

Solaris mtmalloc (archived), 2003

Anatomy of a Program in Memory, 2009

A History of malloc, 2010

Heap and allocators, 2015
Understanding glibc malloc
The Origins of Malloc, 2017

GrapheneOS hardened_malloc, 2019

Simulation of High-Performance Memory Allocators, Risco-Martin, 2024

Posted by egberts on Tue 20 January 2026 in research. Tags: comparison, malloc, arena.

Categories

HowTo
JavaScript
research
security

Tag cloud

Bind9

DNS

environment variables

OpenSSH

DNSSEC

OpenSSL

comparison

ssh

Python

Linux

systemd

gateway

Firefox

Debian

Mozilla

Exim4

security

Gentoo

JavaScript

debugging

vim

SMTP

fail2ban

Pelican

DHCP

nftables

libvirt

libmusl

ISP

Mach

router

netfilter

bison

musl

Postfix

mail

dhclient

syntax

http

Bro

SVG

python-graphviz

graphviz

DOT

QEMU

CUPS

regex

checklist

CSP

web

malware

API

Verizon

Zeek

ATT

sshd

configuration

match

malloc

IM

VXLAN

network

color

terminal

neovim

xfce4terminal

gnome-terminal

EBNF

debug

compiler

gcc

cc

XML

UEFI

Dell

python3-graphviz

development

MTA

BIMI

SSHFP

PKI

Sendmail

X509v3

gdb

dhcpd

ASUS

ports

split-horizon

lpr

OpenSMTPd

WireGuard

bootup

debian9

design

file layout

TCP

algorithm

rst

exploit

markdown

Privacy

Blog

HowTo
JavaScript
research
security

Egbert NetworksPowered by Pelican and m.css.

The comparison of arena architecture within the malloc() system addresses the challenges of memory allocation in modern, multithreaded environments where the heap often becomes a performance bottleneck. When multiple threads simultaneously interact with the memory allocator, serialization occurs, causing performance degradation as the number of processors increases. Consequently, programs are advised to minimize frequent memory allocations and deallocations, especially upon receiving network packets. The evolution of memory allocation systems has progressed through several stages: starting with stack-based allocation, moving to dynamic allocation using linked-list and bucket-heap mechanisms based on size classes, and the introduction of garbage collection algorithms. The arena concept emerged in 2006 as a third pool, intended to manage distinct memory types, such as memory banks or structures related to NUMA architectures, as well as memory affinity tied to specific CPU cores.

The development of the memory allocation system involved distinct evolutions in both the frontend and backend components. The frontend manages the memory provided to the application, evolving through stages like link-list free space management, heap-bucket size classes, owner encoding, and the introduction of structures like thread-specific local allocation buffers (TLABs) and epoch encoding. The backend is responsible for returning unused or fragmented memory blocks to the operating system to reduce the overall resident set size. Backend strategies have evolved to include techniques like the buddy algorithm, binary buddy allocation, and span-based allocators, such as the BIPOP Table, aimed at managing fragmented memory efficiently.

The competition among various memory allocators is structured around balancing thread safety, cache utilization, NUMA awareness, and fragmentation control. Allocators like dlmalloc served as an early foundation, but modern systems feature highly specialized implementations such as jemalloc, tcmalloc, and mimalloc, each designed to mitigate contention and improve scalability. These modern allocators incorporate multi-arena management, per-thread caches, and lock-free fast paths to reduce synchronization overhead. The choice of allocator depends heavily on the workload characteristics, such as whether the system is highly contended, memory-limited, latency-sensitive, or operating in a NUMA environment.

The characteristics of atomic contention and memory locality further differentiate these systems. For instance, while older allocators like dlmalloc faced high contention due to global structures, newer implementations like jemalloc manage contention by utilizing arena-local metadata and thread affinities, leading to lower overall atomic operations. Regarding NUMA awareness, some allocators explicitly support NUMA policies, allowing for better memory locality and reduced cross-node traffic, which is critical in multi-socket server environments.

Benchmark-oriented performance evaluations reveal significant differences. Allocators optimized for small object throughput, like tcmalloc, excel in this area due to per-CPU caches, while mimalloc is noted for excellent latency predictability. For workloads involving high contention, the benefits of multi-arena designs and thread affinity provided by jemalloc and snmalloc are demonstrated in minimizing cacheline bouncing and contention. Specific recommendations guide the selection based on the bottleneck: for highly contended multithreaded scenarios, jemalloc or mimalloc are recommended to minimize atomic latency. For NUMA-aware servers, snmalloc demonstrates superior performance by prioritizing NUMA-first design and locality. For small object workloads, tcmalloc is advantageous, and for scenarios demanding strong security and scalability, snmalloc and mimalloc are preferred. Ultimately, selecting an allocator requires a decision grounded in the specific operational context and the anticipated memory access patterns of the application.