6. Memory management
- 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 :
-
- > 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. When doing so, the pools state prior
- to the flush will also be reported to stderr when the process runs in
- foreground.
-
- 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.