# 6. Memory Management

> Memory allocation, limits, pools, buffers, and process sizing

---

LLMS index: [llms.txt](/llms.txt)

---

<!-- Generated by scripts/generate-haproxy-docs.py from pinned upstream text. -->

HAProxy uses a simple and fast pool-based memory management. Since it relies on a small number of
different object types, it's much more efficient to pick new objects from a pool which already
contains objects of the appropriate size than to call malloc() for each different size. The pools
are organized as a stack or LIFO, so that newly allocated objects are taken from recently released
objects still hot in the CPU caches. Pools of similar sizes are merged together, in order to limit
memory fragmentation.

By default, since the focus is set on performance, each released object is put back into the pool it
came from, and allocated objects are never freed since they are expected to be reused very soon.

On the CLI, it is possible to check how memory is being used in pools thanks to the "show pools"
command:

```shell
> show pools
Dumping pools usage. Use SIGQUIT to flush them.
  - Pool cache_st (16 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccc40=03 [SHARED]
  - Pool pipe (32 bytes): 5 allocated (160 bytes), 5 used, 0 failures, 2 users, @0x9ccac0=00 [SHARED]
  - Pool comp_state (48 bytes): 3 allocated (144 bytes), 3 used, 0 failures, 5 users, @0x9cccc0=04 [SHARED]
  - Pool filter (64 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 3 users, @0x9ccbc0=02 [SHARED]
  - Pool vars (80 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccb40=01 [SHARED]
  - Pool uniqueid (128 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9cd240=15 [SHARED]
  - Pool task (144 bytes): 55 allocated (7920 bytes), 55 used, 0 failures, 1 users, @0x9cd040=11 [SHARED]
  - Pool session (160 bytes): 1 allocated (160 bytes), 1 used, 0 failures, 1 users, @0x9cd140=13 [SHARED]
  - Pool h2s (208 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccec0=08 [SHARED]
  - Pool h2c (288 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cce40=07 [SHARED]
  - Pool spoe_ctx (304 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccf40=09 [SHARED]
  - Pool connection (400 bytes): 2 allocated (800 bytes), 2 used, 0 failures, 1 users, @0x9cd1c0=14 [SHARED]
  - Pool hdr_idx (416 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd340=17 [SHARED]
  - Pool dns_resolut (480 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccdc0=06 [SHARED]
  - Pool dns_answer_ (576 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccd40=05 [SHARED]
  - Pool stream (960 bytes): 1 allocated (960 bytes), 1 used, 0 failures, 1 users, @0x9cd0c0=12 [SHARED]
  - Pool requri (1024 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd2c0=16 [SHARED]
  - Pool buffer (8030 bytes): 3 allocated (24090 bytes), 2 used, 0 failures, 1 users, @0x9cd3c0=18 [SHARED]
  - Pool trash (8062 bytes): 1 allocated (8062 bytes), 1 used, 0 failures, 1 users, @0x9cd440=19
Total: 19 pools, 42296 bytes allocated, 34266 used.
```

The pool name is only indicative, it's the name of the first object type using this pool. The size
in parenthesis is the object size for objects in this pool. Object sizes are always rounded up to
the closest multiple of 16 bytes. The number of objects currently allocated and the equivalent
number of bytes is reported so that it is easy to know which pool is responsible for the highest
memory usage. The number of objects currently in use is reported as well in the "used" field. The
difference between "allocated" and "used" corresponds to the objects that have been freed and are
available for immediate use. The address at the end of the line is the pool's address, and the
following number is the pool index when it exists, or is reported as -1 if no index was assigned.

It is possible to limit the amount of memory allocated per process using the "-m" command line
option, followed by a number of megabytes. It covers all of the process's addressable space, so that
includes memory used by some libraries as well as the stack, but it is a reliable limit when
building a resource constrained system. It works the same way as "ulimit -v" on systems which have
it, or "ulimit -d" for the other ones.

If a memory allocation fails due to the memory limit being reached or because the system doesn't
have any enough memory, then haproxy will first start to free all available objects from all pools
before attempting to allocate memory again. This mechanism of releasing unused memory can be
triggered by sending the signal SIGQUIT to the haproxy process.

During a reload operation, the process switched to the graceful stop state also automatically
performs some flushes after releasing any connection so that all possible memory is released to save
it for the new process.
