【问题标题】:Erlang change VM process initial size. Tune Erlang VMErlang 更改 VM 进程的初始大小。调整 Erlang 虚拟机
【发布时间】:2023-03-06 01:44:01
【问题描述】:

首先我必须提到,我运行在经过调整以支持 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.

【问题讨论】:

    标签: memory process erlang server


    【解决方案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, Size}{sndbuf, Size} 传递给 gen_tcp:listen。它可以显着减少内存占用。

    【讨论】:

    • 忘了说,这些选项记录在inet模块中。
    猜你喜欢
    • 2013-05-22
    • 2023-03-16
    • 2013-05-25
    • 2012-06-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    相关资源
    最近更新 更多