Erlang:内存使用情况数据不一致

And*_*ong 1 erlang

当我运行WebSocket测试时,发现以下有趣的内存使用结果:

服务器已声明,无连接

[{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
Run Code Online (Sandbox Code Playgroud)

100K连接

[{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
Run Code Online (Sandbox Code Playgroud)

200K连接

(重新启动服务器并从0连接创建,而不从情况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
Run Code Online (Sandbox Code Playgroud)

htop提供了带有“ System:”和“ Erlang:”的图,其他是来自erlang shell的memory()调用的输出。请查看总居住时间和erlang居住时间。当没有连接时,这两个大致相同,连接数为100K,驻留内存比总数大一点;如果连接数为200K,则驻留内存几乎是总数的两倍。

有人可以解释吗?

tko*_*wal 6

对于您的查询,最可能的答案是内存碎片。

分配OS内存非常昂贵,因此Erlang会尝试为您管理内存。当Erlang分配内存时,它将创建一个称为“载体”的实体,该实体由许多“块”组成。Erlang内存(总计)报告所有块大小的总和(实际使用的内存)。操作系统报告所有载体大小的总和(已使用和预分配的内存总和)。块大小和载波大小的总和都可以从Erlang VM中读取。如果(块大小)/(载波大小)<< 1,则VM很难释放载波。可能有许多大型运输公司仅使用了两个区块。您可以使用erlang:system_info({allocator,Type})来阅读它。但是有一种更简单的方法。您可以使用Recon库进行检查:

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

首先检查:

recon_alloc:fragmentation(current).
Run Code Online (Sandbox Code Playgroud)

接下来:

recon_alloc:fragmentation(max).
Run Code Online (Sandbox Code Playgroud)

这应该解释Erlang VM和OS报告的总内存之间的差异。如果要通过websocket发送许多小消息,则可以通过使用以下两个选项运行Erlang来减少碎片:

erl +MBas aobf +MBlmbcs 512
Run Code Online (Sandbox Code Playgroud)

第一种选择将块分配策略从最佳匹配更改为最佳顺序寻址,这可以帮助将更多块压缩到第一载波中,第二个选择减小最大多块载波大小,从而使载波更小(这将使释放它们更容易)。