当我运行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
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
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
带有“System:”和“Erlang:”的数字是htop提供的,其他是从erlang shell输出的memory()调用。请查看总和和二郎住宿记忆。当没有连接时,这两个大致相同,有100K连接,驻留内存比总数大一点,有200K连接,驻留内存几乎是总数的两倍。
任何人都可以解释一下吗?
答案 0 :(得分:5)
你的质疑最可能的答案是内存碎片化。
分配操作系统内存非常昂贵,因此Erlang会尝试为您管理内存。 当Erlang分配内存时,它会创建一个名为" carrier"的实体,它由许多"块"组成。 Erlang内存(总计)报告所有块大小(实际使用的内存)的总和。 OS报告所有载波大小的总和(使用和预分配的内存总和)。可以从Erlang VM读取块大小和载波大小的总和。如果(块大小)/(载波大小)<< 1,比VM更难以释放运营商。可能有许多大型运营商只使用了几个街区。你可以用:erlang:system_info({allocator,Type})来读它。但有一种更简单的方法。您可以使用Recon库进行检查:
http://ferd.github.io/recon/recon_alloc.html
首先检查:
recon_alloc:fragmentation(current).
和下一个:
recon_alloc:fragmentation(max).
这应该解释Erlang VM和OS报告的总内存之间的差异。如果您通过websockets发送许多小消息,可以通过运行带有2个选项的Erlang来减少碎片:
erl +MBas aobf +MBlmbcs 512
第一个选项会将块分配策略从最佳匹配更改为地址顺序最佳拟合,这可能有助于将更多块压缩到第一个载波中,第二个减少最大多块载波大小,这会使载波更小(这应该可以使它们更容易释放)