ERlang堆溢出

发布于 2024-10-03 12:49:00 字数 440 浏览 7 评论 0原文

我有一个相当多的程序..

它几乎完成了..

但是我在运行大约 12 小时后看到堆崩溃。

我记得听说过如果你不递归堆栈构建,你就不能以某种方式对 erlang 进行编程。谁能提供一个例子吗?

还有什么方法可以实时监控正在堆积的进程吗?

问候

编辑-怎么样

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();

     _ -> continue
  end,
  loop().

I have quite a program..

Its almost complete..

However I am seeing a heap crash after about 12 hours of running.

I remember hearing that you can't program erlang in a certain way if not when you recurse the stack builds up. Can anyone provide an example of that??

And also is there any way to have a realtime monitor of what process' are stacking up?

Regards

EDIT - What about

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();

     _ -> continue
  end,
  loop().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时光匆匆的小流年 2024-10-10 12:49:00

即使您的编辑不是尾递归:

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();
      _ -> continue 
  end,
  loop().

一个函数的执行顺序是:receive ... end,loop()。现在,如果您收到 {sys, _} 消息,将从接收内部调用 loop/0,将上面的执行顺序转换为相当于

 loop() ->
      receive
          loop() ->
               receive
                  ...
               end,
               loop(),
      end,
      loop() ->
         ...

:问题是,如果您从接收中调用 loop(),VM 仍然必须存储返回点,以便在 loop() 之后就地运行 loop()代码>接收。

要使函数尾部递归,您需要执行以下任一操作:

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg);
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply;
      _ -> continue 
  end,
  loop().

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();
      _ -> loop()
  end.

调用 loop() 确实始终是函数中最后要做的事情。

Even your edit is not tail-recursive:

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();
      _ -> continue 
  end,
  loop().

The order of execution for one function is: receive ... end, loop(). Now, if you get a {sys, _} message, loop/0 will be called from within the receive, transforming the order of execution above into something equivalent to:

 loop() ->
      receive
          loop() ->
               receive
                  ...
               end,
               loop(),
      end,
      loop() ->
         ...

The problem is that if you call loop() from within the receive, the VM still has to store the return point in order to run the loop() in place after the receive.

To make your function tail-recursive, you would need to do either:

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg);
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply;
      _ -> continue 
  end,
  loop().

or

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();
      _ -> loop()
  end.

Where calling loop() really is always the last thing to be done in the function.

江心雾 2024-10-10 12:49:00

进程循环必须是尾递归的。

不要

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop()
  end,
  io:format("Message is processed~n", []).

请参阅:http://www.erlang.org/ doc/efficiency_guide/processes.html

The process loop must be tail-recursive.

DO NOT

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop()
  end,
  io:format("Message is processed~n", []).

See: http://www.erlang.org/doc/efficiency_guide/processes.html

江南烟雨〆相思醉 2024-10-10 12:49:00

类似的东西可以用于监视系统中进程的当前堆使用情况。只需将其放入循环 gen_server 中的打印输出中,或者每隔一段时间在 shell 中运行它即可。

lists:reverse(lists:keysort(2,
   [{Pid,catch element(2,process_info(Pid,total_heap_size))} || Pid <- processes()])).

Something like this could be used for monitoring the current heap usage of processes in you system. Just put it in a printout in a looping gen_server or just run it in the shell every once in a while.

lists:reverse(lists:keysort(2,
   [{Pid,catch element(2,process_info(Pid,total_heap_size))} || Pid <- processes()])).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文