关于进程的内存回收疑问

93 views
Skip to first unread message

郎咸武

unread,
Jan 14, 2014, 8:08:19 AM1/14/14
to erlang-china
Hi All.
我这几天在项目中遇到一个封装DB进程的gen_server 进程特别消耗内存。每个进程大约会占用300~450M内存. 如果是10个这样进程内存一下在消耗接近4G。如果调用erlang:garbage_collect/1这些内存会释放掉的。推断,这些内存已经不再使用只是垃圾回收器没有回收而已(这只我的推断,求赐教),合适触发回收呢?我一直没弄明白。
我为了进一步确认问题。我把问题程序做简化为[1],再次测试,内存一直不回收(时间超出1小时),。
测试步骤:
1、
R变量存储的是19489条记录
(如[{"author_id","users-a9KsYTIRdrq3iuAywiLRE2BGd3Y"},{"timestamp","2013-07-17 10:47:36"},{"time_int",63541277256},{"title",[233,155,133,229,133,184,231,139,172,229,136,155,232,136,170,230,181,183,229,164,169,230,150,135,229,143,176,232,133,149,232,161,168]},{"id","info-137429256786232"}])
2、得到进程Pid
      (tre...@192.168.16.50)5> Pid = test4:get_pid()
3、发送数据之前进制状态
(tre...@192.168.16.50)7> erlang:process_info(Pid, memory).
{memory,2656}
(tre...@192.168.16.50)8> erlang:process_info(Pid).        
[{current_function,{test4,loop,0}},
 {initial_call,{test4,loop,0}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[]},
 {dictionary,[]},
 {trap_exit,false},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.31.0>},
 {total_heap_size,233},
 {heap_size,233},
 {stack_size,1},
 {reductions,1},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,0},
                      {minor_gcs,0}]},
 {suspending,[]}]

4、 发送R数据
(tre...@192.168.16.50)9> Pid ! {self(),R}
{<0.52.0>,
 {ok,[{1,
       [[{"author_id","users-a9KsYTIRdrq3iuAywiLRE2BGd3Y"},
         {"timestamp","2013-07-17 10......................
5、再次查看状态,内存有了明显的增加
(tre...@192.168.16.50)11> erlang:process_info(Pid, memory).
{memory,51356672}
(tre...@192.168.16.50)12> erlang:process_info(Pid).        
[{current_function,{test4,loop,0}},
 {initial_call,{test4,loop,0}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[]},
 {dictionary,[]},
 {trap_exit,false},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.31.0>},
 {total_heap_size,6419485},
 {heap_size,6419485},
 {stack_size,1},
 {reductions,2002},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,0},
                      {minor_gcs,0}]},
 {suspending,[]}]
6、再次发送R数据
(tre...@192.168.16.50)13> Pid ! {self(),R}.                
{<0.52.0>,
 {ok,[{1,
7、内存使用继续增加
(tre...@192.168.16.50)14> erlang:process_info(Pid, memory).
{memory,125381272}
(tre...@192.168.16.50)15> erlang:process_info(Pid).        
[{current_function,{test4,loop,0}},
 {initial_call,{test4,loop,0}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[]},
 {dictionary,[]},
 {trap_exit,false},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.31.0>},
 {total_heap_size,15672560},
 {heap_size,15672560},
 {stack_size,1},
 {reductions,4003},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,0},
                      {minor_gcs,0}]},
 {suspending,[]}]

目前很困惑内存为什么会一直不断增加,继续发数据内存还会继续增加,请赐教解决方法。
(tre...@192.168.16.50)23> erlang:process_info(Pid, memory).
{memory,195907792}


我的环境是:
Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]和
Linux jason-lxw 3.2.0-55-generic #85-Ubuntu SMP Wed Oct 2 12:29:27 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

[1]代码:
  1 -module(test4).
  2 -export([get_pid/0,
  3          get_data/1,
  4          get_pids/1,
  5          loop/0]).
  6 
  7 get_pids(L) ->
  8     get_pids(0, L).
  9 
 10 get_pids(0, L) ->
 11     L;
 12 get_pids(N, R) ->
 13     NewR = [get_pid()|R],
 14     get_pids(N-1, NewR).
 15 
 16 get_pid()->
 17      spawn_opt(?MODULE, loop, [], [{fullsweep_after,0}]).
 18      %spawn(?MODULE, loop, []).                                                                                                                   
 19 
 20 get_data(Pid) ->
 21      Pid ! {self(), get}.
 22 
 23 loop() ->
 24     receive
 25         {From, Data} ->
 26             From ! Data,
 27             loop()
 28     end.

--
只为成功找方法,不为失败找理由

Roowe羅立威

unread,
Jan 14, 2014, 11:13:32 AM1/14/14
to erlang...@googlegroups.com
试下将min_bin_vheap_size改小些,内存详细相关可以参考下http://www.cnblogs.com/me-sa/archive/2011/11/13/erlang0014.html 以及其引用的文章。话又说回来,erlang不是应该小消息大计算吗?你们为啥一次性传那么大的消息


--
您收到此邮件是因为您订阅了 Google 网上论坛的“Erlang China”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到 erlang-china...@googlegroups.com
要查看更多选项,请访问 https://groups.google.com/groups/opt_out。



--
Blog:www.iroowe.com
Twittertwitter.com/roowe

郎咸武

unread,
Jan 14, 2014, 6:41:19 PM1/14/14
to erlang-china
我曾考虑过是否违反了消息大计算原则,可我问题开始于DB进程进程消耗内存过大。谢谢你 我试试。
只为成功找方法,不为失败找理由

郎咸武

unread,
Jan 15, 2014, 12:24:12 AM1/15/14
to erlang-china
 spawn_opt(?MODULE, loop, [], [{min_bin_vheap_size, 1}, {fullsweep_after, 1}, {min_heap_size, 1}]).  
这样创建的进程但是查看时没有发生改变,是fullsweep_after起作用了
 erlang:process_info(Pid).     
[{current_function,{test4,loop,0}},
 {initial_call,{test4,loop,0}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[]},
 {dictionary,[]},
 {trap_exit,false},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.31.0>},
 {total_heap_size,233},
 {heap_size,233},
 {stack_size,1},
 {reductions,1},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,1},
                      {minor_gcs,0}]},
 {suspending,[]}]



在 2014年1月15日 上午12:13,Roowe羅立威 <bestl...@gmail.com>写道:



--
只为成功找方法,不为失败找理由

Feng Yu

unread,
Jan 15, 2014, 2:54:48 AM1/15/14
to erlang...@googlegroups.com
1. min_bin_vheap_size 解决的是vheap的问题,简单的说目前binary属于vheap, 而楼主发的数据是列表不在vheap的控制范围。具体参看:http://blog.yufeng.info/archives/tag/vheap

2. erlang垃圾回收是基于per process的,而且是在process运行期间,发现内存不够了才开始回收。换句话说:如果进程不活跃,内存是不会被回收的。

3. 内存在使用的不会被回收,包括消息引用(听起来像废话)。

4. 违反小消息大计算原则。




余锋(褚霸)
专注高性能容错分布式服务器,实践数据库存储引擎
http://blog.yufeng.info



2014/1/15 Roowe羅立威 <bestl...@gmail.com>

郎咸武

unread,
Jan 15, 2014, 3:22:21 AM1/15/14
to erlang-china
谢谢 老大的回复。

数据我们用的是riak,因实际使用过程中,特别是查询慢的操作如mapreduce和riak_search,很容易把数据库连接池消耗完,导致其他操作会出现失败情况。所以就加大连接数调整到(512个)。内存告警问题就更突出了。查了好多资料,一般都像mysql数据建议10个就够用了。


在 2014年1月15日 下午3:54,Feng Yu <mryu...@gmail.com>写道:
1. min_bin_vheap_size 解决的是vheap的问题,简单的说目前binary属于vheap, 而楼主发的数据是列表不在vheap的控制范围。具体参看:http://blog.yufeng.info/archives/tag/vheap

2. erlang垃圾回收是基于per process的,而且是在process运行期间,发现内存不够了才开始回收。换句话说:如果进程不活跃,内存是不会被回收的。
实际项目中用poolboy实现的DB驱动。,我就是把DB连接 放到一个gen_server中。这个gen_server进程内存一直不释放,我才尝试写一个loop来测试的。查看了一些资料,论论上内存能及时回收。但实际中,却把内存消耗光导致整个节点crash。 我现在只好临时在每次调用gen_server进程时,先执行一下erlang:garbage_collect/1。我目前不确定此方法一定可靠。请赐教。
 
 
 

3. 内存在使用的不会被回收,包括消息引用(听起来像废话)。

4. 违反小消息大计算原则。
这个进程是查询数据库,现在已经违反了这个原则。有没有除了减少返回结果的数量之外的方法?



--
只为成功找方法,不为失败找理由

Feng Yu

unread,
Jan 15, 2014, 7:12:08 AM1/15/14
to erlang...@googlegroups.com
内存的问题recon有一整套解决方案:
https://github.com/ferd/recon


余锋(褚霸)
专注高性能容错分布式服务器,实践数据库存储引擎
http://blog.yufeng.info



2014/1/15 郎咸武 <langx...@gmail.com>

郎咸武

unread,
Jan 15, 2014, 8:29:25 PM1/15/14
to erlang-china
谢谢, 我查一下
Reply all
Reply to author
Forward
0 new messages