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:本文非權威,僅爲我的思考總結

相關文章
相關標籤/搜索