系統技術非業餘研究 » 量化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) [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級別的,我們將之排除掉,避免對平均時間的很大幹擾。
然後我們執行上面的測試程式,我們收集到資料先下圖:
從圖可以看出,我們的schedule每秒執行17萬次左右,每次的代價大概是3個us左右。
我們再配合執行 erlang:statistics(context_switches)以及{_, Reds} = erlang:statistics(reductions) 就可以更準確的看出來上下文切換和執行的規約數字,見下圖:
考慮到stap統計的時候需要用到鎖,對目標程式的干擾還是很大的,我們來對比下有無干擾二種情況下的pingpong效能:
3> ipctest:pingpong().
100012.63959739232
4> ipctest:pingpong().
768416.6022861623
也就是說真實的類似pingpong排程開銷大概是測試到的1/7, 大概是0.5us左右。可見小訊息大計算是必要的。
小結: 量化資料是研究的基礎, 這裡拋磚引玉,希望引起大家的思考。
祝玩的開心!
Post Footer automatically generated by wp-posturl plugin for wordpress.