Почему этот код erlang съедает так много памяти? - PullRequest
2 голосов
/ 24 декабря 2009

Я прохожу через «Программирование Эрланга» Чезарини и Томпсона (О'Рейли), и я принял решение 4-2, но после игры с ним есть две проблемы:

  1. Каждый раз, когда я запускаю go / 3, «werl.exe» в windows жует X объем ОЗУ. Каждый последующий звонок занимает одну и ту же сумму и никогда не возвращается.

  2. Если я запускаю go (Message, 10000,10), он съедает 1,4 ГБ ОЗУ и вылетает

Я думал, что во втором случае Эрланг должен справиться с этим без проблем из того, что я читал, поэтому я предполагаю, что я как-то ввел утечку памяти? Я читаю разделы об утечках памяти и хвостовой рекурсии и не вижу, что я делаю неправильно.

Заранее спасибо.

-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) ->
    [].

Ответы [ 2 ]

2 голосов
/ 24 декабря 2009

ProcList содержит список Pids всех порожденных процессов. Этот список получен всеми процессами. Для вашего примера это означает 10.000 x 10.000 Пид за каждый ход. Это довольно много памяти!

Если не удается настроить сборщик мусора, чтобы избавиться от списка, как только список будет получен, это не сработает ... попробуйте вызвать erlang:garbage_collect() до вызова waitMessage() tail.

0 голосов
/ 24 декабря 2009

Я не могу быть полностью уверен, не увидев «аварийный дамп», но подозреваю, что следующее может вызывать некоторое горе:

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

потому что ваш список источников показывает, что

-module(processRing). имя модуля отличается от того, что вы пытаетесь заставить spawn действовать (имя модуля - первый параметр).

Другими словами: вы пытаетесь создать огромное количество процессов, но каждый из них будет неуспешным, и я подозреваю, что «сборка мусора» займет некоторое время для очистки.

...