为什么这段 erlang 代码会占用这么多内存?

发布于 2024-08-15 16:37:19 字数 1376 浏览 2 评论 0原文

我正在阅读 Cesarini 和 Thompson 的“Erlang 编程”(O'Reilly),并提出了 4-2 的解决方案,但在尝试之后出现了两个问题:

  1. 每次我运行 go/3 时,“werl Windows 中的“.exe”会占用 X 数量的 RAM。随后的每个调用都会占用相同的数量,并且永远不会被回收。

  2. 如果我运行 go(Message,10000,10) 它会占用 1.4GB RAM 并崩溃

我认为在我的第二种情况,从我读到的内容来看,Erlang 应该可以处理这个问题,所以我的猜测是我以某种方式引入了内存泄漏?我阅读了有关内存泄漏和尾递归的部分,但没有看到我做错了什么。

提前致谢。

-module(processRing).
-export([waitMessage/0,go/3]).

% Spawn M processes and pass Message around to each process N times
go(Message,M,N) ->

    ProcList = buildList(M),
    [H | T ] = ProcList,
    register(firstProc,H),
    H ! {self(), T, ProcList, Message, N}.

waitMessage() ->
    receive 
        {_, _, _, _, 0} ->
            io:format("end!", []);

        {From, [H|T], AllProcs, Message, N} ->
            %io:format("~w:~w from:~w~n n=~w",[self(),Message,From,N]),
            H ! {self(), T, AllProcs, Message, N},
            waitMessage();

        {From, [], AllProcs, Message, N} ->
            io:format("~w:~w (Last in list) from:~w n=~w~n",[self(),Message,From,N]),
            firstProc ! {self(), AllProcs, AllProcs, Message, N - 1},
            waitMessage();

        Other ->
            io:format("other:~w~n",[Other])
    end.

buildList(N) when N > 0 ->
    [spawn(processRing,waitMessage,[]) | buildList(N - 1)];

buildList(0) ->
    [].

I'm going through Cesarini and Thompson's "Erlang Programming" (O'Reilly) and I made a solution to 4-2 but after playing around with it there are two problems:

  1. Every time I run go/3, "werl.exe" in windows chews up X amount of RAM. Every subsequent call takes up the same amount and it's never reclaimed.

  2. If I run go(Message,10000,10) it eats up 1.4GB RAM and crashes

I thought that in my second case, Erlang should handle this no problem from what I've been reading, so my guess is that I've somehow introduced a memory leak? I read the sections on memory leaks and tail recursion and don't see what I'm doing wrong.

Thanks in advance.

-module(processRing).
-export([waitMessage/0,go/3]).

% Spawn M processes and pass Message around to each process N times
go(Message,M,N) ->

    ProcList = buildList(M),
    [H | T ] = ProcList,
    register(firstProc,H),
    H ! {self(), T, ProcList, Message, N}.

waitMessage() ->
    receive 
        {_, _, _, _, 0} ->
            io:format("end!", []);

        {From, [H|T], AllProcs, Message, N} ->
            %io:format("~w:~w from:~w~n n=~w",[self(),Message,From,N]),
            H ! {self(), T, AllProcs, Message, N},
            waitMessage();

        {From, [], AllProcs, Message, N} ->
            io:format("~w:~w (Last in list) from:~w n=~w~n",[self(),Message,From,N]),
            firstProc ! {self(), AllProcs, AllProcs, Message, N - 1},
            waitMessage();

        Other ->
            io:format("other:~w~n",[Other])
    end.

buildList(N) when N > 0 ->
    [spawn(processRing,waitMessage,[]) | buildList(N - 1)];

buildList(0) ->
    [].

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

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

发布评论

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

评论(2

白云不回头 2024-08-22 16:37:19

ProcList 包含所有生成进程的 Pids 列表。所有进程都会收到此列表。对于您的示例,这意味着每轮 10.000 x 10.000 Pids。这可是相当大的内存啊!

除非垃圾收集可以设置为在收到列表后立即删除列表,否则这是行不通的...尝试在 waitMessage() 之前调用 erlang:garbage_collect() 尾部调用。

ProcList contains the list of Pids of all spawned processes. This list is received by all processes. For your example this means 10.000 x 10.000 Pids for each turn. That's quite a lot of memory!

Unless garbage collection can be set to get rid of the list as soon as the list is received, this won't work... try calling erlang:garbage_collect() before the waitMessage() tail calls.

走走停停 2024-08-22 16:37:19

如果没有看到“崩溃转储”,我无法完全确定,但我怀疑以下内容可能会造成一些悲伤:

[spawn(chap9q1,waitMessage,[]) | buildList(N - 1)];

因为您的源列表显示

-module(processRing). 该模块的命名与您尝试获取的 spawn 不同code> 进行操作(模块名称是第一个参数)。

换句话说:您正在尝试构建大量进程,但每个进程都会失败,我怀疑“垃圾收集”将需要一些时间来清理。

I can't be entirely sure without seeing the "crash dump" but I suspect that the following might be causing some grief:

[spawn(chap9q1,waitMessage,[]) | buildList(N - 1)];

because your source listing shows that

-module(processRing). the module is named something different from what you are trying to get spawn to act on (module name is the first parameter).

In other words: you are trying to build a huge number of processes but every one of them will be failing and I suspect that the "garbage collection" will take some time to clean-up.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文