当我运行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,则驻留内存几乎是总数的两倍。
有人可以解释吗?
对于您的查询,最可能的答案是内存碎片。
分配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)
第一种选择将块分配策略从最佳匹配更改为最佳顺序寻址,这可以帮助将更多块压缩到第一载波中,第二个选择减小最大多块载波大小,从而使载波更小(这将使释放它们更容易)。