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