2010-11-18 90 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()])).