论坛首页 综合技术论坛

高強度的port(Pipe)的性能測試

浏览 1921 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-09-14   最后修改:2009-09-14
在我的項目里面, 很多運算logic是由外部的程序來計算的 那么消息先透過pipe發到外部程序,外部程序讀到消息, 處理消息, 寫消息, erlang程序讀到消息, 這條鏈路很長,而且涉及到pipe讀寫,上下文切換,這個開銷是很大的.但是具體是多少呢?

我設計了個這樣的ring. 每個ring有N個環組成, 每個環開個port. 當ring收到個數字的時候 如果數字不為0, 那么把這個數字發到外部成程序,這個外部程序echo回來數字,收到echo回來的消息后,把數字減1,繼續傳遞.當數字減少到0的時候 銷毀整個ring.

root@nd-desktop:~/test#ulimit -n 1024 /* 注意這個數字非常重要 它影響了Erlang程序3個地方 1. epoll的句柄集大小 2. MAX_PORT 以及port的表格大小 3. open_port的時候 子進程關閉的文件句柄大小*/

root@nd-desktop:~/test# cat pipe_ring.erl
-module(pipe_ring).

-export([start/1]).
-export([make_relay/1, run/3]).

make_relay(Next)->
    Port = open_port({spawn, "/bin/cat"}, [in, out, {line, 128}]),
    relay_loop(Next, Port).

relay_loop(Next, Port) ->
    receive
        {Port, {data, {eol, Line}}} ->
            Next ! (list_to_integer(Line) - 1),
            relay_loop(Next, Port);
        K when is_integer(K) andalso K > 0 ->
            port_command(Port, [integer_to_list(K), "\n"]),
            relay_loop(Next, Port);
        K when is_integer(K) andalso K =:=0 ->
            port_close(Port),
            Next ! K
end.

build_ring(K, Current, N, F) when N > 1 ->
    build_ring(K, spawn(?MODULE, make_relay, [Current]), N - 1, F);

build_ring(_, Current, _, F) ->
    F(),
    make_relay(Current).

run(N, K, Par) ->
    Parent = self(),
    Cs = [spawn(fun ()-> Parent!run1(N, K, P) end) || P<-lists:seq(1, Par)],
    [receive _-> ok end || _<-Cs].
   
run1(N, K, P)->
    T1 = now(),
    build_ring(K, self(), N, fun ()-> io:format("(ring~w setup time: ~ws)~n", [P, timer:now_diff(now(), T1) /1000]), self() ! K end).

start(Args) ->
    Args1 = [N, K, Par] = [list_to_integer(atom_to_list(X)) || X<-Args],
    {Time, _} = timer:tc(?MODULE, run, Args1),
    io:format("(total run (N:~w K:~w Par:~w) ~wms ~w/s)~n", [N, K, Par, round(Time/1000), round(K*Par*1000000/Time)]),
    halt(0).

root@nd-desktop:~/test# erl +Bd -noshell +K true -smp disable -s pipe_ring start 10 100000 8
(ring1 setup time: 0.021s)
(ring2 setup time: 0.02s)
(ring3 setup time: 0.019s)
(ring4 setup time: 0.03s)
(ring5 setup time: 0.018s)
(ring6 setup time: 0.031s)
(ring7 setup time: 0.027s)
(ring8 setup time: 0.039s)
(total run (N:10 K:100000 Par:8) 23158ms 34546/s)

參數的意義:
N K Par
N:ring有幾個環 每個環開一個port
K:每個環傳遞多少消息
Par: 多少ring一起跑

總的消息數是 K * Par.

我們可以看到 每秒可以處理大概 3.4W個消息 我有2個核心. 也就是說每個消息的開銷大概是 30us. 每個port的創建時間不算多, 1ms一個.

root@nd-desktop:~/test# dstat
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw
33  18  50   0   0   1|   0     0 | 438B 2172B|   0     0 |5329    33k
42  11  48   0   0   0|   0     0 | 212B  404B|   0     0 |5729    58k
41  11  49   0   0   0|   0     0 | 244B 1822B|   0     0 |5540    59k
40  11  49   0   0   0|   0     0 | 304B  404B|   0     0 |4970    60k

注意上面的csw 達到6W每秒.

root@nd-desktop:~/test# pstree
├─sshd─┬─sshd─┬─bash───pstree
     │      │      └─bash───man───pager
     │      ├─sshd───bash─┬─beam─┬─80*[cat]
     │      │             │      └─{beam}
     │      │             └─emacs
     │      ├─sshd───bash───emacs
     │      └─sshd───bash───nmon

我們運行了80個echo程序(/bin/cat)

讀者有興趣的話可以用systemtap 詳細了解 pipe的讀寫花費,以及context_switch情況, 具體腳本可以向我索要.

root@nd-desktop:~# cat /proc/cpuinfo
processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 23
model name      : Pentium(R) Dual-Core  CPU      E5200  @ 2.50GHz
stepping        : 6
cpu MHz         : 1200.000
cache size      : 2048 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 1
initial apicid  : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 10
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts pni dtes64 monitor ds_cpl em
bogomips        : 4987.44
clflush size    : 64
power management:

結論是: 用port的這種架構的開銷是可以接受的.


   发表时间:2009-09-14  
文章很赞。这下可以安心的用port了。
0 请登录后投票
   发表时间:2009-09-14  
linux thread switch 19us  所以大量的csw是高性能的杀手!
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics