Search code examples
erlangheap-memoryspawn

spawn/1 and sharing of the outer variables


For the following fragment:

outer_func(State) ->
    spawn(fun()-> do_something(State) end).

Will State be shared or deep-copied to the spawned process heap?


Solution

  • It will be deep copied. Here's a simple demo:

    1> State = lists:seq(1, 1000000).
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,
     23,24,25,26,27,28,29|...]
    2> DoSomething = fun(State) -> io:format("~p~n", [process_info(self(), memory)]) end.
    3> spawn(fun() -> DoSomething(State) end), spawn(fun() -> DoSomething(State) end), spawn(fun() -> DoSomething(State) end).
    {memory,16583520}
    {memory,16583520}
    {memory,16583520}
    

    In contrast to that, here's the output when the state is a large binary which is never "deep" copied when shared with multiple processes:

    1> State = binary:copy(<<"a">>, 50000000).
    <<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...>>
    2> DoSomething = fun(State) -> io:format("~p~n", [process_info(self(), memory)]) end.
    3> spawn(fun() -> DoSomething(State) end), spawn(fun() -> DoSomething(State) end), spawn(fun() -> DoSomething(State) end).
    {memory,8744}
    {memory,8744}
    {memory,8744}
    

    So a process with a list of integers from 1 to 1 million used about 16MB of memory while the one with a large binary used 8KB (the binary should actually be a negligible part of that).