Erlang: Inconsistent Memory Usage Metrics

When I run my WebSocket test I found the following interesting memory usage results:

Server declared, no connection

[{total,573263528},
 {processes,17375688},
 {processes_used,17360240},
 {system,555887840},
 {atom,472297},
 {atom_used,451576},
 {binary,28944},
 {code,3774097},
 {ets,271016}]
44 processes,
System:705M, 
Erlang Residence:519M

      

100K connections

[{total,762564512},
 {processes,130105104},
 {processes_used,130089656},
 {system,632459408},
 {atom,476337},
 {atom_used,456484},
 {binary,50160},
 {code,3925064},
 {ets,7589160}]
100044 processes,
System: 1814M, 
Erlang Residence: 950M

      

200K connections

(restart the server and create connections from 0, not continue from example 2)

[{total,952040232},
 {processes,243161192},
 {processes_used,243139984},
 {system,708879040},
 {atom,476337},
 {atom_used,456484},
 {binary,70856},
 {code,3925064},
 {ets,14904760}]
200044 processes,
System:3383M, 
Erlang: 1837M

      

The numbers with "System:" and "Erlang:" are provided by htop, others are deduced from the memory () of the call from the erlang shell. Please take a look at the shared memory and erlang residency. When there is no connection, the two devices are about the same, with 100K connections, the residence memory is slightly larger than the total, with 200K connections, the residence memory is almost double.

Can someone please explain?

+1


source to share


1 answer


The most likely answer for your request is memory fragmentation.

OS memory allocation is expensive, so Erlang tries to manage memory for you. When Erlang allocates memory, it creates an object called "carrier", which is made up of many "blocks". Erlang's memory (total) displays the sum of all block sizes (actually used memory). The OS reports the sum of all carrier sizes (sum of used memory and pre-allocated). Both block sizes and carrier sizes can be read from the Erlang VM. If (block sizes) / (carrier sizes) <1, than the VM is having a hard time freeing the carriers. There can be many large media out there using only a few blocks. You can read it with: erlang: system_info ({allocator, Type}). but there is an easier way. You can test it using the Recon library:

http://ferd.github.io/recon/recon_alloc.html

Check first:

recon_alloc:fragmentation(current).

      



and further:

recon_alloc:fragmentation(max).

      

This should explain the difference between the shared memory reported by the Erlang VM and the OS. If you are sending a lot of small messages through web ports, you can reduce fragmentation by running Erlang with two parameters:

erl +MBas aobf +MBlmbcs 512

      

The first option will change the block allocation strategy to the best fit for optimal address allocation, which can help compress more blocks on the first media, and second, reduce the maximum multiblock carrier size, which makes the carriers smaller (this should make them easier to release).

+4


source







All Articles