Erlang内存吃紧之解决思路

首先使用erlang:memory()肯定是哪一个部份内存吃紧,根据输出的内容,比对内存占用大小,有针对性地进行分析。在erlang系统里内存的单位为word,经过erlang:system_info(wordsize)接口能够看到一个word占用多少个字节。如32位系统是4字节,64位系统是8字节。node

> memory().                                     
[{total,13079568},
 {processes,4214248},
 {processes_used,4213320},
 {system,8865320},
 {atom,202481},
 {atom_used,189725},
 {binary,52800},
 {code,4618749},
 {ets,263848}]
> erlang:system_info(wordsize).
8

1.进程占用过多内存的状况(processes值较大)shell

可用etop查找内存占用高的进程,也能够排序全部进程(erlang:processes/0可得到全部进程pid)的内存占用(erlang:process_info(Pid, heap_size)可得到进程内存占用)。数据结构

找到目标进程后分析该进程的信息process_info(Pid)进一步发现问题,一般找到目标进程,就能从代码和进程状态中分析出问题。可能的问题有:app

      是否陷入非尾递归的死循环?(若是一直吃CPU不吃内存则多是尾递归的死循环致使)oop

      进程的主循环是否没用尾递归,致使调用栈无限增加?fetch

      是否存入过多没必要要的数据到进程字典中且没有及时erase?优化

      gen_server的state中是否存入过多内容?atom

etop memory示例:spa

> spawn(fun() -> etop:start([{sort, memory}]) end).
<0.34.0>
   
========================================================================================
 nonode@nohost                                                             11:50:35
 Load:  cpu         0               Memory:  total       12642    binary         29
        procs      28                        processes    4076    code         4454
        runq        0                        atom          198    ets           256
   
Pid            Name or Initial Func    Time    Reds  Memory    MsgQ Current Function
----------------------------------------------------------------------------------------
<0.7.0>        application_controll     '-'    7270  426440       0 gen_server:loop/6   
<0.12.0>       code_server              '-'   98774  142688       0 code_server:loop/1  
<0.26.0>       erlang:apply/2           '-'    9840  122072       0 shell:get_command1/5
<0.3.0>        erl_prim_loader          '-'  181804   62856       0 erl_prim_loader:loop
<0.23.0>       user_drv                 '-'    4122   26496       0 user_drv:server_loop
<0.0.0>        init                     '-'    2347   24520       0 init:loop/1         
<0.32.0>       erlang:apply/2           '-'    1668   21424       0 shell:eval_loop/3   
<0.11.0>       kernel_sup               '-'    1543   12152       0 gen_server:loop/6   
<0.25.0>       group:server/3           '-'    1613   11864       0 group:more_data/5   
<0.6.0>        error_logger             '-'     227    6904       0 gen_event:fetch_msg/
========================================================================================
>etop:stop().

 

2.ets表占用过多内存的状况(ets值较大)code

   排序全部ets表(ets:all/0可得到全部ets表名Tab)的内存占用(ets:info(Tab, memory)可得到内存占用),找出最占内存的ets表进行分析。ets表过大,是由于insert过多内容,却不多delete。分析表的功能,寻求恰当的方式作优化,节源开流。

ets表内存战斗排序示例:

> lists:sublist(lists:reverse(lists:keysort(2,[{T, ets:info(T, memory)} || T <- ets:all()])), 10).
[{1,11220},
 {4098,7022},
 {ac_tab,942},
 {inet_db,497},
 {global_locks,302},
 {global_names,302},
 {global_names_ext,302},
 {global_pid_names,302},
 {global_pid_ids,302},
 {inet_cache,302}]

一些优化的思路:

      按期将不经常使用数据清理出内存

      选择更优的数据结构(如选择binary存字符串,而不是list)

      优化掉冗余的数据(如相同数据拷贝多份的状况,能够优化成只保存一份数据

 

PS:本文非权威,仅为我的思考总结

相关文章
相关标签/搜索