调查使用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