[erlang-questions] message ring test (memory allocation question)

Hynek Vychodil vychodil.hynek@REDACTED
Sat Mar 8 20:40:37 CET 2008


On Tue, Mar 4, 2008 at 4:54 PM, Allen McPherson <mcpherson@REDACTED> wrote:

> -- Re-post.  Hope I don't generate a duplicate post but I just signed
> up.
>
>
> Hello,
>
> First post here from a new Erlang programmer.  As an exercise I
> have written the message ring benchmark that Joe talked about in
> his book:
>
> -module(cleanring).
> -compile(export_all).
>
> start(N, Msg) ->
>     StartPid = launch(self(), N),
>     StartPid ! {Msg, self(), 0},
>     receive
>        {MsgRecvd, _FromPid, _Hop} -> done
>     end,
>     StartPid ! die,
>     MsgRecvd.
>
> launch(Pid, N) ->
>     FromPid = spawn(fun() -> loop(Pid) end),
>     if
>        N =:= 1 -> FromPid;
>        true    -> launch(FromPid, N-1)
>     end.
>
> loop(ToPid) ->
>     receive
>        {Term, _FromPid, Hop} ->
>            ToPid ! {Term, self(), Hop+1},
>            loop(ToPid);
>        die ->
>            ToPid ! die
>     end.
>
>
> If I run as follows, it dies in malloc:
>
> 1> c(cleanring).
> 2> L = lists:seq(1,100000).
> 3> cleanring:start(32000, L).
>
> If I make L a binary (in a restarted erl shell) it runs fine (and too
> fast to believe):
>
> 1> c(cleanring).
> 2> L = lists:seq(1,100000).
> 3> LL = term_to_binary(L).
> 4> cleanring:start(32000, LL).
>
> Is the runtime somehow just passing around a pointer to LL by virtue
> of it being a binary?  I'm not sure why it doesn't crash as the first
> run did.
>
> You are right, binary messages are send only by passing pointer, but
normal structures don't. Normal structures are send by copying because
shared nothing processes strategy. Erlang GC don't free message immediately
but after some amount of reductions (function calls) and your receive loop
in each process is reduced only one time than your big message is kept in
memory.

Possible solution is explicit garbage collect after message send but it
decrease performance for small messages (more than 20%):

loop(ToPid) ->
    receive
       {Term, _FromPid, Hop} ->
           ToPid ! {Term, self(), Hop+1},
           garbage_collect(), % explicit garbage collect message
           loop(ToPid);
       die ->
           ToPid ! die
    end.

Also, if you spot anything really wrong with the program I'd
> appreciate a
> heads up.  I'm new to Erlang and am sometimes not sure if the code I
> write
> is in the "right mindset" (functional programming-wise).


I think your program is OK, but when you must pass many times huge message,
good strategy is avoid this or send binary.

>
> Thanks
> --
> Al
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions
>



-- 
--Hynek (Pichi) Vychodil
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080308/dad6c7f2/attachment.htm>


More information about the erlang-questions mailing list