调查使用binary最多TOPN进程
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: 调查使用binary最多TOPN进程
Erlang程序是非常健壮的,通常一个典型的虚拟机里面跑很多进程,这些进程即使有bug,按照erlang的哲学是快速死掉,系统留下异常堆栈,很容易发现问题。照理说erlang是很少crash的,但实际情况不是这样的。
在erlang VM crash的案例中,我们会发现大部分的网络服务器的原因都是binary内存不够申请不出来,所以内存短缺是最致命的影响稳定的因素。通常设计良好的erlang程序,按照otp的设计哲学不会占用太多内存的,即使占用了gc也很快就会回收的,除了binary这个内存使用大户。
比如说网络服务器程序,我们用binary来保存用户的封包,我们无法预测用户要发送多大的包,比如上限是50M,如果我们的系统有1000个这样的用户,在极端情况下,我们是要耗用50G内存的。通常在这种情况下,我们拿不出这么多物理内存,然后crash就很大概率会发生。
调查哪些进程用掉了最多的binary内存就很有必要了,我们在极端情况下,可以选择性的杀掉这些内存,保护自己不至于毁灭。
erlang:process_info有个未公开的选项 binary用来获取这个进程拥有的binary情况。
我们看下它的实现:
static Eterm bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh) { struct erl_off_heap_header* ohh; Eterm res = NIL; Eterm tuple; for (ohh = oh->first; ohh; ohh = ohh->next) { if (ohh->thing_word == HEADER_PROC_BIN) { ProcBin* pb = (ProcBin*) ohh; Eterm val = erts_bld_uword(hpp, szp, (UWord) pb->val); Eterm orig_size = erts_bld_uint(hpp, szp, pb->val->orig_size); if (szp) *szp += 4+2; if (hpp) { Uint refc = (Uint) erts_smp_atomic_read_nob(&pb->val->refc); tuple = TUPLE3(*hpp, val, orig_size, make_small(refc)); res = CONS(*hpp + 4, tuple, res); *hpp += 4+2; } } } return res; } Eterm process_info_aux(Process *BIF_P, Process *rp, Eterm rpid, Eterm item, int always_wrap) { ... case am_binary: { Uint sz = 3; (void) bld_bin_list(NULL, &sz, &MSO(rp)); hp = HAlloc(BIF_P, sz); res = bld_bin_list(&hp, NULL, &MSO(rp)); break; } ... }
这个选项会返回一个bin情况tuple的列表,每个tuple的第一个是binary的地址,第二个是大小,第三个是引用次数。
我们来演示下如何使用:
Read more…
Post Footer automatically generated by wp-posturl plugin for wordpress.
Recent Comments