ERlang HEAP溢出

时间:2010-11-18 14:57:54

标签: erlang heap overflow

我有很多节目..

它差不多完整..

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

我记得听说过,如果不是在递归堆栈时你不能以某种方式编写erlang。任何人都可以提供一个例子吗?

还有什么方法可以实时监控哪些流程正在堆叠?

此致

编辑 -

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

     _ -> continue
  end,
  loop().

3 个答案:

答案 0 :(得分:8)

即使您的编辑尾递归:

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()之后运行receive。< / p>

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

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()确实总是在函数中完成的最后一件事。

答案 1 :(得分:2)

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

不要

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

答案 2 :(得分:1)

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

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