[Ericsson Utvecklings AB]

sl_alloc

C LIBRARY

sl_alloc

C LIBRARY SUMMARY

A memory allocator for short lived memory blocks in the Erlang Run-Time System (ERTS internal library).

DESCRIPTION

This page mainly describes sl_alloc release 2. By default sl_alloc release 1 is enabled. See System Flags Affecting sl_alloc on how to enable sl_alloc release 2.

The main idea behind sl_alloc is to use one allocator for short lived memory blocks and another allocator which puts more effort in finding a good fit (perhaps the best fit) for long lived memory blocks. The other allocator is expected to do a much better job with the long lived memory blocks when it is not disturbed by short lived blocks with less fragmentation in the areas where long lived blocks are placed as a result. Putting more effort in finding a good fit for long lived memory blocks than short lived is more rewarding since it will have a longer effect. By putting less effort in finding a good fit for short lived memory blocks the CPU load will decrease. The fragmentation in these areas is expected to increase, but as long as it is kept on a reasonable level the overall fragmentation can be reduced at the same time as the CPU load is reduced.

sl_alloc manages multiple areas, called carriers, in which memory blocks are placed. A carrier is either placed in a memory segment created by a call to the system call mmap() or in the heap segment (by a call to malloc()). Multiblock carriers are used for storage of several small blocks, and singleblock carriers are used for storage of one large block.

A "good fit" algorithm is used for management of blocks in multiblock carriers. Segregated free lists with a maximum search depth (in each list) are used in order to find a good fit fast. Boundary tags (headers and footers) in free blocks are used for fast coalescing.

The other allocator (typically malloc()) will normally manage the heap segment. By placing sl_alloc carriers in memory segments created by mmap(), sl_alloc will disturb the other allocator as little as possible. Really large requests to sl_alloc are placed in singleblock carriers in order to avoid creating really large holes. The downside of this is an increased number of mmap/munmap calls which can give a performance penalty.

sl_alloc release 1 only manages singleblock carriers, that is, blocks that are placed in multiblock carriers by sl_alloc release 2 are allocated by malloc() in release 1.

Mainly Erlang heap data (Erlang heaps, and message buffers) has been classified as short lived, and most of the other data has been classified as long lived. Erlang heap data has been classified as short lived because it is frequently moved between memory blocks due to copying garbage collection.

"Other data" that may consume large amounts of memory is mainly ETS data and large binaries. ETS data and large binary data have been classified as long lived since the data will not be moved until it is removed.

One cannot say that all ETS and binary data are long lived and all Erlang heap data is short lived, but it should be safe to say that most ETS and binary data are more long lived than most Erlang heap data.

The use of sl_alloc mainly has an advantage when there is a significant amount of ETS and/or binary data since malloc will be able to do a better job with this data when it does not have to bother with the Erlang heap data.

If almost all data in the system is being stored on the process heaps, the situation is not as good since the main part of the memory will be allocated by sl_alloc which probably fragments the memory more than malloc. The situation is not as bad as it seems though. When the data is stored on Erlang heaps it will be stored in larger but fewer blocks than if it had been stored in ETS tables which simplifies the job for sl_alloc. sl_alloc is also quite good at preventing fragmentation even though malloc probably is better. When memory consumption decreases heavily, sl_alloc decreases the total amount of used pages far better than a malloc implementation only using the heap segment. sl_alloc also still has the advantage of reducing CPU load compared to a malloc implementation that is putting more effort in finding a good fit. But in the case that the memory consumed mainly consist of Erlang heap data, the malloc implementation used causes a lot less fragmentation than sl_alloc, and there is a memory shortage, it may be best not to enable sl_alloc release 2.

System Flags Affecting sl_alloc

Warning!

Only use these flags if you are absolutely sure what you are doing. Unsuitable settings may cause serious performance degradation (and even a system crash) at any time during operation.

The following sl_alloc flags can be passed to the Erlang virtual machine (see also erl(1)):

+Se BOOL
Enable sl_alloc (default true if mmap() is available; otherwise, false).
+Sr RELEASE
Enable a specific release of sl_alloc (default 1). Currently release 1 (version 1.0) and release 2 (version 1.9.3) can be enabled.
+Ssbct SIZE_IN_KB
Singleblock carrier threshold (default 128 Kb). Blocks larger than this threshold will be placed in singleblock carriers.
+Smmc AMOUNT
Max mmap carriers (default 64). Maximum number of carriers placed in memory segments created by mmap(). When this limit has been reached, new carriers will be placed on the heap segment (by using malloc() instead of mmap()).
+Ssbcmt RATIO
Singleblock carrier move threshold (default 80%). A block in a singleblock carrier which is resized by sl_realloc() will be left in an unchanged singleblock carrier if the block fits, the ratio of unused memory (in percent) is less than this threshold, and a (copying) move will be avoided; otherwise, it will be moved into a new singleblock carrier or into a multiblock carrier.
+Smcs SIZE_IN_KB
Main carrier size (default 1.25 Mb). The size of the main multiblock carrier. The main multiblock carrier is placed in the heap segment and is never removed.
+Sscs SIZE_IN_KB
Smallest multiblock carrier size (default 1.25 Mb). The size of the first multiblock carrier if no main carrier exist (that is, if the "main carrier size" is 0).
+Slcs SIZE_IN_KB
Largest multiblock carrier size (default 50 Mb). The maximum size of a multiblock carrier.
+Scgr RATIO
Multiblock carrier growth ratio (default 25%). The ratio of growth in size of multiblock carriers when the number of carriers increases. The size of a multiblock carrier is based on the "smallest multiblock carrier size", the number of existing multiblock carriers, and the "multiblock carrier growth rate".
+Smbsd DEPTH
Max block search depth (default 3). Free blocks are placed in segregated free lists which are searched when trying to satisfy a request. Each free list contains blocks of sizes in a specific range. The max block search depth sets a limit on the maximum number of blocks to inspect in a free list during the search.
+Scos BOOL
Carrier order search (default false). When turned on (true), each carrier will be searched in the order of creation for a suitable free block to use for an allocation request.

Note!

Most of these flags are highly implementation dependent, and they may be changed or removed without prior notice.

sl_alloc is not obliged to strictly use the settings that has been passed to it.

The +Ssbcmt, +Smmc, +Smcs, +Sscs, +Slcs, +Smbsd, and +Scos flags will be silently ignored when sl_alloc release 1 is enabled.

See Also

erl(1)

AUTHORS

Rickard Green - support@erlang.ericsson.se

erts 5.1.1
Copyright © 1991-2002 Ericsson Utvecklings AB