2010-11-18 98 views
1

我有相当多的程序..二郎堆溢出

它几乎完全..

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

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

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

问候

编辑 - 约

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

    _ -> continue 
    end, 
    loop(). 
+0

您的编辑是尾递归,这意味着它不会在堆栈上构建任何东西。 – Lukas 2010-11-18 16:51:21

+2

作为@TERRIBLE建议非常正确地指出你的编辑是不是尾递归 – rvirding 2010-11-19 08:25:42

回答

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仍然需要存储返回点以便在receive之后运行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()真的是总是的最后一件事情在做功能。

+0

伟大的答案,我会给你更多的票,如果我可以! – BAR 2010-11-19 05:22:39

1

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

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