我有很多节目..
它差不多完整..
但是我在运行大约12个小时后看到堆崩溃。
我记得听说过,如果不是在递归堆栈时你不能以某种方式编写erlang。任何人都可以提供一个例子吗?
还有什么方法可以实时监控哪些流程正在堆叠?
此致
编辑 -
怎么样?loop() ->
receive
{sys, Msg} ->
handle_sys_msg(Msg),
loop();
{From, Msg} ->
Reply = handle_msg(Msg),
From ! Reply,
loop();
_ -> continue
end,
loop().
答案 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()])).