Archive

Archive for September, 2009

Literal XML in Erlang with parse_transform/2

September 30th, 2009 Comments off

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Literal XML in Erlang with parse_transform/2

原文地址:http://hyperstruct.net/2007/6/26/literal-xml-in-erlang-with-parse-transform-2

One of the things I dislike about Erlang is that it severely impairs bragging opportunities. Yesterday I wrote a module that allows writing literal XML in the source and have it parsed into Erlang structures at compile time—sort of like E4X minus the manipulation goodies at runtime (at least for now).

You write:

Doc = '<greeting>Hello!</greeting>',
io:format("~p~n", [Doc]).

And it prints…

{xmlElement,greeting,
            greeting,
            [],
            {xmlNamespace,[],[]},
            [],
            1,
            [],
            [{xmlText,[{greeting,1}],1,[],"Hello!",text}],
            [],
            "/tmp",
            undeclared}

In most languages I’m familiar with, this would have granted the author instant Yacc-demigod status. With Erlang… it was less than 40 LOC. Hardly something you’d wear at a party.

Anyway, this code owes everything to Philip’s writings. It also uses parse_transform/2, and “programmers are strongly advised not to engage in parse transformations and no support is offered for problems encountered”. So unless you, like me, are still at the kid-in-a-candy-shop stage of Erlang experience, think twice before using this in production, ok?

The code is here http://repo.hyperstruct.net/inline_xml/

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: 网络编程 Tags:

erlang的abstract code

September 30th, 2009 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: erlang的abstract code

erlang的abstract code是编译的中间代码,很多工具如 erl_pp lint什么的都是根据这个做调整的。还有进一步的parse_transform也是基于它的。 所以,了解它非常重要。 erts user guide里面详细了描述了它的定义。我这里展示的是如何获取到某个模块的abstract code 以便进一步研究:

[root@localhost ~]# erl -s hello
Erlang R13B02 (erts-5.7.3) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

hello world
[root@localhost ~]# cat hello.erl
-module(hello).
-export([start/0]).

start()->
    io:format("hello world~n",[]).
[root@localhost ~]# erlc +debug_info hello.erl
[root@localhost ~]# erl
Erlang R13B02 (erts-5.7.3) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.3  (abort with ^G)
1> rp(beam_lib:chunks(hello, [abstract_code])).
{ok,{hello,[{abstract_code,{raw_abstract_v1,[{attribute,1,
                                                        file,
                                                        {"./hello.erl",1}},
                                             {attribute,1,module,hello},
                                             {attribute,2,export,[{start,0}]},
                                             {function,4,start,0,
                                                       [{clause,4,[],[],
                                                                [{call,5,
                                                                       {remote,5,{atom,5,io},{atom,5,format}},
                                                                       [{string,5,"hello world~n"},{nil,5}]}]}]},
                                             {eof,6}]}}]}}
ok
2>

对着文档开始好好分析吧。 Have fun!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: 网络编程 Tags:

Latest News from the Erlang/OTP team at Ericsson September 5 2009

September 28th, 2009 Comments off

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Latest News from the Erlang/OTP team at Ericsson September 5 2009

原文地址:http://erlang-factory.com/upload/presentations/167/KennethLundin-LatestnewsfromtheErlangOTPteamatEricssonErlang_Workshop2009.pdf

Coming Open Source releases

OTP R13B02 September 23

OTP R13B03 November 25

OTP R13B04 Jan-Feb 2010

OTP R13B05 ???

OTP R14B May-June 2010

OTP R14B01

OTP R14B02

Plans for later releases

Multicore performance improvements

– Delayed deallocation, let the right scheduler do it (R13B03)

– Improved handling of process table

– Separate allocators per scheduler

– Use NUMA info for grouping of schedulers

– Separate poll sets per scheduler (IO)

– Support Scheduler bindings, cpu_topology on Windows as well.

– Optimize Erlang applications in Erlang/OTP

– Fine grained parallelism, language and library functions.

– Better and more benchmarks

New way to build the documentation

– Using XSLTPROC to produce html, man and XSL-FO

– Using Apache FOP to produce PDF

Easier to interface C libraries and to make your own ”BIFs”

– Dynamically linked in BIF’s (for C-code , easier to write and more efficient

than drivers)

Support for validation in xmerl_sax_parser

BIFs for search in binaries (EEP-?)

红色的部分 好期待哦。。。

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: 网络编程 Tags:

节点间通讯的通道微调

September 23rd, 2009 10 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 节点间通讯的通道微调

erlang节点间通讯是可以配置的,默认的是inet_tcp 。当2个节点要沟通的时候,net_kernel模块会负责建立必要的连接。 inet_tcp会调用底层的gen_tcp进行数据发送接受。 rpc或者节点间的消息交互都是通过这个port出去的。

在分布节点间,有时候会有大量的消息流动,那么所有的消息都是通过这个port出去 进来,所以这个port的性能极大的影响了节点间通讯的效率。那么有时候, 我们会想微调这个port的参数,根据业务的特点实现效率最大化,但是port如何得到呢?

node_port(Node)->
    {_, Owner}=lists:keyfind(owner, 1, element(2, net_kernel:node_info(Node))),
    hd([P|| P<-erlang:ports(), erlang:port_info(P, connected) == {connected,Owner}])

有了Port, 那么我们就可以设置tcp port的水位线,buffer等等。

inet:setopts(node_port('xx@nd-desktop'), [{high_watermark, 131072}]).

另外要注意 nodeup nodedown可能会换了个tcp链接 要注意重新获取。

还有另外一种方法,设置所有gen_tcp的行为, 比如以下方法:

erl -kernel inet_default_connect_options '[{sndbuf, 1048576}, {high_watermark, 131072}]'

但是这个影响面非常大, 影响到正常tcp的参数了。

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags: , ,

实验Erlang语法对应的opcode 让你对erlang理解更深

September 20th, 2009 2 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 实验Erlang语法对应的opcode 让你对erlang理解更深

Erlang作为一门FP语言,和传统的语言结构一样, 有模块, 有函数, 有语句, 有判断, 有循环, 还有特别的模式匹配。 那么这些在底层是如何运作的。 我在底下给大家做个简单的实验,让大家一窥内部的细节,让大家写码的时候知道个大概。

erlang的VM作为register based的VM, 大概有400条指令.指令分为hot, normal, cold 3大类别。beam_emu.c是vm的实现,hot和cold指令在编译的时候 由脚本生成的,include到beam_emu去的。 hot是热门的操作如list, tuple操作, cold的就是比较偏的指令。

erlang的编译器支持生成汇编码, 让我们的研究成可能,具体用法是 erlc +”‘S'” m.erl
会生成m.S 这个汇编文件.

root@nd-desktop:~# cat gram.erl
-module(gram).
-export([start/1]).

start([X])->
   %% bif
    X1 = list_to_integer(atom_to_list(X)),

%% list
    W =[1,2,3],
    W1 = [4|W],

    K=[W1,9],

    %% constant fold
    A = 1 + 2,
   
  %% if
    B =
        if X1 + A > 0 -> 5;
           true -> 4
        end,

   %% case
    C =
    case B of
        {x, T} -> T;
        5 -> a1;
        3 -> a2;
        2 -> 1.0;
        other -> 2;
        true -> 3
    end,

   %% receive
    D =
    receive
        a1 ->
            2 + 1.2;
        2 -> 3;
        {tag, N}->N;
        a2 -> 5;
        _ -> ok
    after A ->
            timeout
    end,
   
    %% anon fun
    E = fun (1)-> D;
            (x)-> 2;
            (y)-> C;
            (<<"12">>)->1;
            (_) -> error
            end,

    F = E(D),

    %% fun
    G = f(B),

    io:format("~p~p~p~p~n",[F, G,W,K]),

    done.


f(1)-> 1;
f(2) ->2;
f(3) ->3;
f(4) ->4;
f(5) ->5;
f(x1) ->1;
f(x2) ->2;
f(x3) ->3;
f(x4) ->4;
f(x5) ->5;
f({x,1}) -> 1;
f({x,2}) ->2;
f({x,3}) ->3;
f({x,4}) ->4;
f({x,5}) ->5;
f(<<1:8, X:32, "xyz", F/float>>) -> {X, F};
f(_) -> err.
root@nd-desktop:~# erlc +"'S'" gram.erl
root@nd-desktop:~# cat gram.S
{module, gram}.  %% version = 0
{exports, [{module_info,0},{module_info,1},{start,1}]}.

{attributes, []}.

{labels, 45}. %%每个标签是跳转地址

%%每个指令对应这相应的opcode,在beam_emu中都可以找到。

{function, start, 1, 2}.
  {label,1}.
    {func_info,{atom,gram},{atom,start},1}.
  {label,2}.
    {test,is_nonempty_list,{f,1},[{x,0}]}.
    {get_list,{x,0},{x,1},{x,2}}.
    {test,is_nil,{f,1},[{x,2}]}. 
    {allocate_zero,2,2}.
    {move,{x,1},{x,0}}.
   %% bif调用
    {call_ext,1,{extfunc,erlang,atom_to_list,1}}.
    {call_ext,1,{extfunc,erlang,list_to_integer,1}}.
    %% 符号也是bif
   %% 3= 1 +2 const fold
    {gc_bif,'+',{f,3},1,[{x,0},{integer,3}],{x,1}}.
    %% if 语句是如此简单
    {test,is_lt,{f,3},[{integer,0},{x,1}]}.
    {move,{integer,5},{x,0}}.
    {jump,{f,4}}.
  {label,3}.
    {move,{integer,4},{x,0}}.
  {label,4}.
    {move,{x,0},{y,1}}.
   %% case语句同样是个if else的判断
   
    %% tuple是如何匹配的 效率高
    {test,is_tuple,{f,5},[{x,0}]}.
    {test,test_arity,{f,21},[{x,0},2]}.
    {get_tuple_element,{x,0},0,{x,1}}.
    {get_tuple_element,{x,0},1,{x,2}}.
    {test,is_eq_exact,{f,21},[{x,1},{atom,x}]}.
    {move,{x,2},{x,0}}.
    {jump,{f,12}}.
  {label,5}.
    {test,is_atom,{f,8},[{x,0}]}.
    %% 2分查找
    {select_val,{x,0},{f,21},{list,[{atom,true},{f,6},{atom,other},{f,7}]}}.
  {label,6}.
    {move,{integer,3},{x,0}}.
    {jump,{f,12}}.
  {label,7}.
    {move,{integer,2},{x,0}}.
    {jump,{f,12}}.
  {label,8}.
    {test,is_integer,{f,21},[{x,0}]}.
   %% 编译器会聪明的做这类事情
    {select_val,{x,0},
                {f,21},
                {list,[{integer,2},
                       {f,9},
                       {integer,3},
                       {f,10},
                       {integer,5},
                       {f,11}]}}.
  {label,9}.
    {move,{float,1.0},{x,0}}.
    {jump,{f,12}}.
  {label,10}.
    {move,{atom,a2},{x,0}}.
    {jump,{f,12}}.
  {label,11}.
    {move,{atom,a1},{x,0}}.
  {label,12}.
    {move,{x,0},{y,0}}.

%% receive语句
  {label,13}.
    {loop_rec,{f,19},{x,0}}.
    {test,is_tuple,{f,14},[{x,0}]}.
    {test,test_arity,{f,18},[{x,0},2]}.
    {get_tuple_element,{x,0},0,{x,1}}.
    {get_tuple_element,{x,0},1,{x,2}}.
    {test,is_eq_exact,{f,18},[{x,1},{atom,tag}]}.
   
    %%从消息队列移除
    remove_message.
    {move,{x,2},{x,0}}.
    {jump,{f,20}}.
  {label,14}.
    {test,is_atom,{f,17},[{x,0}]}.
    {select_val,{x,0},{f,18},{list,[{atom,a2},{f,15},{atom,a1},{f,16}]}}.
  {label,15}.
    remove_message.
    {move,{integer,5},{x,0}}.
    {jump,{f,20}}.
  {label,16}.
    remove_message.
    {move,{float,3.2},{x,0}}.
    {jump,{f,20}}.
  {label,17}.
    {test,is_eq_exact,{f,18},[{x,0},{integer,2}]}.
    remove_message.
    {move,{integer,3},{x,0}}.
    {jump,{f,20}}.
  {label,18}.
    remove_message.
    {move,{atom,ok},{x,0}}.
    {jump,{f,20}}.
  {label,19}.
    %% timeout添加到定时器
    {wait_timeout,{f,13},{integer,3}}.
    timeout.
    {move,{atom,timeout},{x,0}}.
  {label,20}.
    %% 闭包
    {move,{x,0},{x,1}}.
    {move,{y,0},{x,0}}.
    {move,{x,1},{y,0}}.
    {make_fun2,{f,39},0,133275192,2}.
    {move,{x,0},{x,1}}.
    {move,{y,0},{x,0}}.
    {trim,1,1}.
    {call_fun,1}.
    {move,{x,0},{x,1}}.
    {move,{y,0},{x,0}}.
    {move,{x,1},{y,0}}.
    {call,1,{f,23}}.
    {test_heap,4,1}.
    %% 列表操作
    {put_list,{x,0},{literal,[[1,2,3],[[4,1,2,3],9]]},{x,0}}.
    {put_list,{y,0},{x,0},{x,1}}.
    {trim,1,0}.
    {move,{literal,"~p~p~p~p~n"},{x,0}}.
    {call_ext,2,{extfunc,io,format,2}}.
    {move,{atom,done},{x,0}}.
    {deallocate,0}.
    return.
  {label,21}.
    {case_end,{x,0}}.


{function, f, 1, 23}.
  {label,22}.
    {func_info,{atom,gram},{atom,f},1}.
  {label,23}.
    {test,bs_start_match2,{f,24},1,[{x,0},0],{x,0}}.
    {test,bs_match_string,{f,33},[{x,0},8,{string,[1]}]}.
    {test,bs_get_integer2,
          {f,33},
          1,
          [{x,0},
           {integer,32},
           1,
           {field_flags,[{anno,[78,{file,"./gram.erl"}]},unsigned,big]}],
          {x,1}}.
    {test,bs_match_string,{f,33},[{x,0},24,{string,"xyz"}]}.
    {test,bs_get_float2,
          {f,33},
          2,
          [{x,0},
           {integer,64},
           1,
           {field_flags,[{anno,[78,{file,"./gram.erl"}]},unsigned,big]}],
          {x,2}}.
    {test,bs_test_tail2,{f,33},[{x,0},0]}.
    {test_heap,3,3}.
    {put_tuple,2,{x,0}}.
    {put,{x,1}}.
    {put,{x,2}}.
    return.
  {label,24}.
    {test,is_tuple,{f,25},[{x,0}]}.
    {test,test_arity,{f,33},[{x,0},2]}.
    {get_tuple_element,{x,0},0,{x,1}}.
    {get_tuple_element,{x,0},1,{x,2}}.
    {test,is_eq_exact,{f,33},[{x,1},{atom,x}]}.
    {test,is_integer,{f,33},[{x,2}]}.
    {select_val,{x,2},
                {f,33},
                {list,[{integer,5},
                       {f,26},
                       {integer,4},
                       {f,27},
                       {integer,3},
                       {f,28},
                       {integer,2},
                       {f,29},
                       {integer,1},
                       {f,30}]}}.
  {label,25}.
    {test,is_atom,{f,31},[{x,0}]}.
    {select_val,{x,0},
                {f,33},
                {list,[{atom,x5},
                       {f,26},
                       {atom,x4},
                       {f,27},
                       {atom,x3},
                       {f,28},
                       {atom,x2},
                       {f,29},
                       {atom,x1},
                       {f,30}]}}.
  {label,26}.
    {move,{integer,5},{x,0}}.
    return.
  {label,27}.
    {move,{integer,4},{x,0}}.
    return.
  {label,28}.
    {move,{integer,3},{x,0}}.
    return.
  {label,29}.
    {move,{integer,2},{x,0}}.
    return.
  {label,30}.
    {move,{integer,1},{x,0}}.
    return.
  {label,31}.
    {test,is_integer,{f,33},[{x,0}]}.
    {select_val,{x,0},
                {f,33},
                {list,[{integer,5},
                       {f,32},
                       {integer,4},
                       {f,32},
                       {integer,3},
                       {f,32},
                       {integer,2},
                       {f,32},
                       {integer,1},
                       {f,32}]}}.
  {label,32}.
    return.
  {label,33}.
    {move,{atom,err},{x,0}}.
    return.

%%这2个函数是complier要硬性加上去的

{function, module_info, 0, 35}.
  {label,34}.
    {func_info,{atom,gram},{atom,module_info},0}.
  {label,35}.
    {move,{atom,gram},{x,0}}.
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.


{function, module_info, 1, 37}.
  {label,36}.
    {func_info,{atom,gram},{atom,module_info},1}.
  {label,37}.
    {move,{x,0},{x,1}}.
    {move,{atom,gram},{x,0}}.
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.

%%匿名函数的命名
{function, '-start/1-fun-0-', 3, 39}.
  {label,38}.
    {func_info,{atom,gram},{atom,'-start/1-fun-0-'},3}.
  {label,39}.
    {test,bs_start_match2,{f,40},3,[{x,0},0],{x,0}}.
    {test,bs_match_string,{f,44},[{x,0},16,{string,"12"}]}.
    {test,bs_test_tail2,{f,44},[{x,0},0]}.
    %% bitstring的代码很优化。
    {move,{integer,1},{x,0}}.
    return.
  {label,40}.
    {test,is_atom,{f,43},[{x,0}]}.
    {select_val,{x,0},{f,44},{list,[{atom,y},{f,41},{atom,x},{f,42}]}}.
   %% 一类的数据放在一起 用二分查找匹配
  {label,41}.
    {move,{x,1},{x,0}}.
    return.
  {label,42}.
    {move,{integer,2},{x,0}}.
    return.
  {label,43}.
    {test,is_eq_exact,{f,44},[{x,0},{integer,1}]}.
    {move,{x,2},{x,0}}.
    return.
  {label,44}.
    {move,{atom,error},{x,0}}.
    return.

所以无论函数match, 表达式match在vm层面都是if else这样的判断。从这个角度来讲if, case这些都只是erlang的语法糖。事实上也是,这些语法都是后来添加的,取悦用户的。

函数匹配是erlang的所有事情的核心。

结论:erlang的compiler很智能,这个VM和lua的非常像, 效率也相当。

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags: , ,

erlang定时器的强度测试

September 15th, 2009 3 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: erlang定时器的强度测试

erlang的定时器在做网络程序的时候几乎无所不在, 语法层面的receive after,IO操作超时,driver内部等都大量使用timer,特别是tcp 在发送接收都有个超时。 如果你有大量的tcp链接, 就意味着大量的定时器。 那么定时器的性能就是个很大的考验。erts的定时器是个timer_wheel实现, 和linux内核用的差不多,大概支持百万级别的规模。 测试如下:

并发开N个进程 每个进程里面0-10秒的随机定时,模拟tcp超时的情况。每个定时器事件的流程是这样的 进程检查消息队列 没消息 注册定时器事件 进程换出 定时器超时 进程换入 处理定时器事件。

root@nd-desktop:~/test# cat ttimer.erl 
-module(ttimer). 
-export([start/1]). 

upmap(F, L) -> 
    Parent = self(), 
    Ref = make_ref(), 
    [receive {Ref, Result} -> Result end 
     || _ <- [spawn(fun() -> Parent ! {Ref, F(X)} end) || X <- L]]. 

loop(0)-> 
    ok; 

loop(Cnt)-> 
        receive after random:uniform(10000) -> cont end, 
        loop(Cnt-1). 

start([A1, A2]) -> 
         Start= now(), 
         N= list_to_integer(atom_to_list(A1)), 
         Cnt = list_to_integer(atom_to_list(A2)), 
         io:format("spawn ~w process, loop ~w~n", [N, Cnt]), 
         upmap(fun loop/1, lists:duplicate(N, Cnt)), 
         io:format("run ~w ms~n", [round(timer:now_diff(now(), Start) /1000)]), 
         done. 
root@nd-desktop:~/test# erl -smp disable -noshell +P 9999999 -s ttimer start 500000 10 -s erlang halt 
spawn 500000 process, loop 10 
run 63201 ms 

单cpu保持在70-80%, 63秒处理了500W个定时器事件, 大概每秒8W.

root@nd-desktop:~/test# cat /proc/cpuinfo 
model name      : Pentium(R) Dual-Core  CPU      E5200  @ 2.50GHz 
bogomips        : 4987.08 

结论: 定时器处理还是比较费时间的。

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags:

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

September 13th, 2009 3 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 高強度的port(Pipe)的性能測試

在我的項目里面, 很多運算logic是由外部的程序來計算的 那么消息先透過pipe發到外部程序,外部程序讀到消息, 處理消息, 寫消息, erlang程序讀到消息, 這條鏈路很長,而且涉及到pipe讀寫,上下文切換,這個開銷是很大的.但是具體是多少呢?

我設計了個這樣的ring. 每個ring有N個環組成, 每個環開個port. 當ring收到個數字的時候 如果數字不為0, 那么把這個數字發到外部成程序,這個外部程序echo回來數字,收到echo回來的消息后,把數字減1,繼續傳遞.當數字減少到0的時候 銷毀整個ring.
/* 注意這個數字非常重要 它影響了Erlang程序3個地方 1. epoll的句柄集大小 2. MAX_PORT 以及port的表格大小 3. open_port的時候 子進程關閉的文件句柄大小*/

root@nd-desktop:~/test#ulimit -n 1024 
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的這種架構的開銷是可以接受的.

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags: , , ,