Erlang 更改 VM 进程的初始大小。调整 Erlang 虚拟机

Posted

技术标签:

【中文标题】Erlang 更改 VM 进程的初始大小。调整 Erlang 虚拟机【英文标题】:Erlang change VM process initial size. Tune Erlang VM 【发布时间】:2015-12-28 15:25:05 【问题描述】:

首先我必须提到,我运行在经过调整以支持 100 万个连接的 CentOS 7 上。我用一个简单的 C 服务器和客户端进行了测试,我连接了 512000 个客户端。我可以连接更多,但我没有足够的 RAM 来生成更多的 linux 客户端机器,因为我可以从一台机器打开 65536 个连接; 8 台机器 * 每台 64000 个连接 = 512000。

我制作了一个简单的 Erlang 服务器,我想使用相同的 C 客户端连接 100 万或 50 万个客户端。我现在遇到的问题与内存有关。对于每个成功的gen_tcp:accept 调用,我都会生成一个进程。大约 50000 个打开的连接在服务器上花费了 3.7 GB RAM,同时使用 C 服务器我可以使用 1.9 GB RAM 打开 512000 个连接。确实,在 C 服务器上,我没有在接受后创建进程来处理东西,我只是在 while 循环中再次调用了接受,但即便如此......网上的人用更少的内存做了这个 erlang 的事情(ejabberd riak)

我认为我传递给 erlang VM 的标志应该可以解决问题。根据我在文档和网络上阅读的内容,这就是我所拥有的:erl +K true +Q 64200 +P 134217727 -env ERL_MAX_PORTS 40960000 -env ERTS_MAX_PORTS 40960000 +a 16 +hms 1024 +hmbs 1024

这是服务器代码,我通过调用start(1, 5001)打开了1个监听5001端口的监听器。

start(Num,LPort) ->
  case gen_tcp:listen(LPort,[reuseaddr, true,backlog,9000000000]) of
    ok, ListenSock ->
      start_servers(Num,ListenSock),
      ok, Port = inet:port(ListenSock),
      Port;
    error,Reason ->
      error,Reason
  end.

start_servers(0,_) ->
  ok;
start_servers(Num,LS) ->
  spawn(?MODULE,server,[LS,0]),
  start_servers(Num-1,LS).

server(LS, Nr) ->
  io:format("before accept ~w~n",[Nr]),
  case gen_tcp:accept(LS) of
    ok,S ->
      io:format("after accept ~w~n",[Nr]),
      spawn(ex,server,[LS,Nr+1]),
      proc_lib:hibernate(?MODULE, loop, [S]);
    Other ->
      io:format("accept returned ~w - goodbye!~n",[Other]),
      ok
  end.

loop(S) ->
  ok = inet:setopts(S,[active,once]),
  receive
    tcp,S, _Data ->
      Answer = 1, % Not implemented in this example
      gen_tcp:send(S,Answer),
      proc_lib:hibernate(?MODULE, loop, [S]);
    tcp_closed,S ->
      io:format("Socket ~w closed [~w]~n",[S,self()]),
      ok
  end.

【问题讨论】:

【参考方案1】:

鉴于此配置,您的 my beam 在启动时消耗了大约 2.5 GB 的内存,甚至没有加载您的模块。

但是,如果您将最大进程数减少到合理的值,例如 +P 60000 进行 50 000 个连接测试,内存消耗会迅速下降。

由于 60 000 个进程限制,VM 仅在启动时使用 527MB 的虚拟内存。

我试图重现您的测试,但不幸的是,在内存不足(由于客户端作业)之前,我只能在系统上启动 30 000 个netcat。但是,我只观察到 VM 内存消耗增加至 570MB

所以我的建议是您的数字来自高启动内存消耗,而不是大量打开的连接。即使这样,您实际上也应该注意统计数据随着打开连接数量的增加而变化,而不是绝对值。

我终于在我的基准测试中使用了以下配置:

erl +K true +Q 64200 +P 60000 -env ERL_MAX_PORTS 40960000 -env ERTS_MAX_PORTS 40960000 +a 16 +hms 1024 +hmbs 1024

所以我已经使用命令启动了客户端

for i in `seq 1 50000`; do nc 127.0.0.1 5001 &  done

【讨论】:

你能把你使用的启动erlang的命令粘贴给我吗? erl 和 args 到底是什么;还有你是如何建立这些联系的?从 erlang 内部,C 客户端?我做了一个 C 客户端【参考方案2】:

除了您已经制作的曲调之外,您还可以调整 tcp 缓冲区。默认情况下,它们采用操作系统默认值,但您可以将 recbuf, Sizesndbuf, Size 传递给 gen_tcp:listen。它可以显着减少内存占用。

【讨论】:

忘了说,这些选项记录在inet模块中。

以上是关于Erlang 更改 VM 进程的初始大小。调整 Erlang 虚拟机的主要内容,如果未能解决你的问题,请参考以下文章

列出 Erlang 中进程可用的可用记录

UITabBarController - 初始帧和调整大小

在调整大小时更改 dataTables 页码

powershell 调整Azure VM磁盘的大小。

system进程ntoskrnl磁盘占用高怎么解决

VM虚拟机下怎么调整Ubuntu的界面大小?装好ubuntu后界面太小了,想调整到合适大小...