首先使用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:本文非权威,仅为我的思考总结