量化Erlang进程调度的代价
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: 量化Erlang进程调度的代价
我们都知道erlang的基本哲学之一就是“小消息大计算”,简单的说就是尽可能的在消息里面携带完整的计算需要的信息,然后计算要尽可能的多,最好远超过消息传递的代价。但是为什么要这样呢?erlang消息发送的效率是很高的, 参见这篇文章
Roughly speaking, I’m seeing 3.4 million deliveries per second one-way, and 1.4 million roundtrips per second (2.8 million deliveries per second) in a ping-pong setup in the same environment as previously – a 2.8GHz Pentium 4 with 1MB cache.
在我的机器上的演示下看看具体的数字:
$ erl Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:16:16] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.9.3.1 (abort with ^G) 1> ipctest:pingpong(). 832296.5692402497 2>
大概83万每秒个消息pingpong,测试程序涉及到二个Erlang进程ping和pong.
一个完整的流程涉及到 1. ping进程运行 2. ping进程等pong消息被切出。 3. pong运行 4. pong等ping消息被切出。这个流程涉及到二次Erlang进程的调度。
这是一个典型的erlang使用的场景,我们现在的问题是到底一个erlang进程调度的开销是多少?
从erts的实现来看,erlang会调用schedule()函数来选择下一个要调度的进程,而真正swapin和swapout的代价并不高,那我们来统计下schedule的开销。
还是祭出我们伟大的stap,写段调查代码先:
$ cat sch.stp
global total, coll_sch, sch
global exclude_sys_schedule
probe process("beam.smp").function("schedule") {
sch[tid()] = gettimeofday_ns();
total++;
}
probe process("beam.smp").function("schedule").return {
tid = tid();
e = gettimeofday_ns() - sch[tid];
if (exclude_sys_schedule && e > 10 * 1000 * 1000 ) coll_sch <<< 0;
else coll_sch <<< e;
}
function print_colls () {
prt_line = 0;
if(@count(coll_sch) >0) {
printf("total %d, avg %d ns\n", total, @avg(coll_sch));
printf("===========erts schedule(ns)===========\n");
print(@hist_log(coll_sch));
prt_line = 1;
}
if(prt_line) printf("--------------------------------------------------------------\n");
delete coll_sch;
delete sch;
delete total;
}
probe timer.s(1) {
print_colls();
}
probe begin {
exclude_sys_schedule = $1
println("x:");
}
$ PATH=/usr/local/lib/erlang/erts-5.9.3.1/bin/:$PATH sudo stap sch.stp 1
x:
如果调度器在不忙或者调度足够多的进程后,需要收割epoll事件,也就是会调用sys_schedule,这个时间通常会是ms级别的,我们将之排除掉,避免对平均时间的很大干扰。
Read more…
Post Footer automatically generated by wp-posturl plugin for wordpress.
Recent Comments