列出垃圾收集

时间:2013-03-07 08:28:21

标签: memory-management garbage-collection erlang

如果我执行以下操作:

List2 = [V || V <- List1, ...]

似乎List2引用了List1和erlang:garbage_collect()不清除内存。如何在没有引用的情况下创建新列表并丢弃旧的列表?

3 个答案:

答案 0 :(得分:1)

在使用垃圾收集的任何语言中,您只需要“丢失”对一段数据的所有引用,然后才能进行垃圾收集。简单地从生成原始列表的函数返回,而不是将其存储在任何其他“持久”位置(例如进程字典)中,应该允许回收内存。

答案 1 :(得分:1)

VM应该管理垃圾收集。如果你使用gen_server,或者使用“自制”server_loop(State),你应该总是使用相同的模式:

server_loop(State) ->
   A = somefunc(State),
   B = receive
          mesg1 -> func1(...);
          ...
       after Timeout ->
          func2(...)
       end,
   NewState = func3(...),
   server_loop(NewState).

只要进程处于活动状态,执行此循环,VM将分配和管理内存区域以存储所有需要的信息(变量,消息队列...... +一些余量)据我所知,有一些备用分配给进程的内存,如果VM在释放后没有尝试快速恢复内存,但如果强制进行垃圾收集,使用erlang:garbage_collect(Pid)可以验证内存是否空闲 - 请参阅例如,吼叫。

startloop() -> spawn(?MODULE,loop,[{lists:seq(1,1000),infinity}]).

loop(endloop) -> ok;
loop({S,T}) ->
    NewState = receive
        biglist -> {lists:seq(1,5000000),T};
        {timeout,V} -> {S,V};
        sizelist -> io:format("Size of the list = ~p~n",[length(S)]),
                            {S,T};
        endloop -> endloop
    after T ->
        L = length(S) div 2,
        {lists:seq(1,L),T}
    end,
    loop(NewState).
    %% Here, NewState is a copy of State or a totally new data, depending on the
    %% received message. In general, for performance consideration it can be 
    %% interesting to take care of the function used to avoid big copies, 
    %% and allow the compiler optimize the beam code 
    %% [H|Q] rather than Q ++ [H] to add a term to a list for example

以及VM中的结果:

2> P = lattice:startloop().
<0.57.0>
...
6> application:start(sasl).  
....
ok
7> application:start(os_mon).
...
ok
...
11> P ! biglist.
biglist
...

%get_memory_data() - &gt; {总计,分配,最坏}

14> memsup:get_memory_data().
{8109199360,5346488320,{<0.57.0>,80244336}}
...
23> P ! {timeout,1000}.             
{timeout,1000}
24> memsup:get_memory_data().
{8109199360,5367361536,{<0.57.0>,80244336}}

最糟糕的情况是循环过程:{&lt; 0.57.0&gt;,80244336}

...
28> P ! sizelist.            
Size of the list = 0
sizelist
...
31> P ! {timeout,infinity}.
{timeout,infinity}
32> P ! biglist.                    
biglist
33> P ! sizelist.          
Size of the list = 5000000
sizelist
...
36> P ! {timeout,1000}.      
{timeout,1000}
37> memsup:get_memory_data().
{8109199360,5314289664,{<0.57.0>,10770968}}

%%请注意上一行中的垃圾收集:{&lt; 0.57.0&gt;,10770968}

38> P ! sizelist.            
sizelist
Size of the list = 156250
39> memsup:get_memory_data().
{8109199360,5314289664,{<0.57.0>,10770968}}
...
46> P ! sizelist.            
Size of the list = 0
sizelist
47> memsup:get_memory_data().
{8109199360,5281882112,{<0.57.0>,10770968}}
...
50> erlang:garbage_collect(P).
true
51> memsup:get_memory_data(). 
{8109199360,5298778112,{<0.51.0>,688728}}
GC后

%%,过程&lt; 0.57.0&gt;不再是最糟糕的情况

答案 2 :(得分:0)

如果您创建这样的新列表,新列表将包含第一个元素,一些元素将在两个列表之间共享。如果您抛弃第一个列表,共享元素仍然可以从新列表中访问,并且不会被视为垃圾。

如何检查第一个列表是否是垃圾回收?你在erlang控制台测试吗?控制台存储评估结果,每个表达式可能是您没有看到列表垃圾收集的原因。