Archive

Posts Tagged ‘dbg’

trace机制新增exception_trace

October 21st, 2011 4 comments

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

本文链接地址: trace机制新增exception_trace

我们在使用Erlang的时候,经常会发现exception被静悄悄得忽略掉了,这点对于诊断问题非常的不友好。R14B04新添加exception_trace帮助用户在异常的时候,得到异常得调用栈,就马上可以解决问题。 这个功能主要面对高级用户,文档里面没怎么描述这个事情,主要的实现在erts的trace模块里面,有兴趣的同学可以自己看看。
我来演示下这个功能:
Read more…

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

Categories: Erlang探索 Tags: ,

Erlang match_spec引擎介绍和应用

October 7th, 2011 2 comments

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

本文链接地址: Erlang match_spec引擎介绍和应用

match_spec是什么呢?

A “match specification” (match_spec) is an Erlang term describing a small “program” that will try to match something (either the parameters to a function as used in the erlang:trace_pattern/2 BIF, or the objects in an ETS table.). The match_spec in many ways works like a small function in Erlang, but is interpreted/compiled by the Erlang runtime system to something much more efficient than calling an Erlang function. The match_spec is also very limited compared to the expressiveness of real Erlang functions.

具体参见这里
说白了它就是个erlang term得过滤器,可以让用户来自己选择需要匹配什么,需要从term里面抽取什么数据。那同学可能就有疑问了,Erlang的函数不是很强大吗,它能做的函数也能做,那为什么要重新费劲做一个呢?
Erlang实现这个match_spec得原因有2个:1. 运行效率 2. 小巧可以在运行期使用。

它的实现思路是: match_spec是个引擎,有自己的语法,先把语句编译成专用的opcode, 然后在在匹配的时候运行opcode,获取结果,可以理解为erlang的DSL。

接下来我带大家先感性的认识下这个DSL:
Read more…

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

seq_trace集群消息链跟踪利器

October 3rd, 2011 Comments off

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

本文链接地址: seq_trace集群消息链跟踪利器

做过网络集群服务器的的同学都知道,集群服务通常由不同的服务器组成,这些不同角色的服务器组合在一起共同完成了特定的服务。一个服务通常需要一个协调者,和不同的工作者。 协调者负责派发任务,接收工作者的完成情况,最终回馈给用户。举个例子来讲,拨打电话:首先需要确认你的号码是在有效的,同时还要看下你的帐号里面有钱不,还要看下你拨打的电话号码是不是由权限,电话打的时候需要扣钱,等等。 这些服务中间的任何一个环节出问题了,服务就不正常了。那么我们在服务出问题的时候,如何定位问题呢?通常的办法是打日志,在所有的参与服务的节点上打开日志记录,之后到所有的节点上收集日志,集中分析日志,相当的麻烦。

这时候seq_trace来救助了,seq_trace的目标就是能够跟踪一条消息经过的所有环节,最终把路径展现给用户。
铺垫材料:
seq_trace工作原理,请参考这里
ttb对seq_trace的支持参考这里
tdbg对seq_trace的支持参考这里
Read more…

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

Categories: Erlang探索 Tags: , , ,

如何找出异常所在的行(新思路)

April 21st, 2010 3 comments

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

本文链接地址: 如何找出异常所在的行(新思路)

在Erlang-china的邮件列表上看到这样的问题:

我的服务经常发生这样的错误,举例:
Error in process <0.33.0> with exit value: {badarg,[{erlang,’++’,[undefined,[{“37”}]]},{groups,doWork,1},
{groups,doWork,1},{groups,manage_clients,1}]}

大意明白,但问题是我使用匹配机制时没考虑到多个函数”doWork/1″出错无法定位到其中一个,这该如何是好?
Erlang是否会像其它语言一样提示某一行出错?

这个问题确实很常见, Erlang的运行期没有给出出错的具体行数, 这给我们定位问题带来了很大的麻烦.

有先驱给出了这样的解决方案 http://mryufeng.javaeye.com/blog/368507 但是这个模块已经很老了, 过时不维护了.

这里我给出另外一个方案, 利用erlang现有的模块来实现的: cover + dbg

cover的工作原理可以参考这篇文章 http://mryufeng.javaeye.com/blog/482204.

原理就是cover编译过的模块会在每行执行前, 先执行ets:update_counter(cover_internal_data_table,{bump,Mod,Fun,1,1,Line},1) 来更新模块某行的执行次数.
那么我们只要截取 ets:update_counter这个动作, 我们就知道改模块最后的执行行, 也就是异常所在的行.

Ok, 原理介绍完毕, 上菜.

[root@centos ~]# cat line.erl

-module(line).
-export([dbg/1]).
-include_lib("stdlib/include/ms_transform.hrl").

dbg(Mod)->
    cover:compile(Mod),
    dbg:tracer(),
    dbg:p(all, [call]),
    dbg:tpl(ets,
            update_counter,
            dbg:fun2ms(fun([_,{bump,Mod,_,_,_,_},1]) ->
                               return_trace()
                       end)),
    ok.

[root@centos ~]# cat hello.erl

-module(hello).
-export([start/0]).

start()->
    a=a,
    A=2,
    C=3,
    A=C-1,
    C=A+1,
    io:format("hello world~n",[]),
    test(C),
    ok.


test(C)->
    A=4,
    A=C,  % Error is on this line.
    ok.

我们可以看到这个hello模块会在hello:test发生异常, A=C这个地方是具体位置. 现在让我们找到行号:

[root@centos ~]# 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> line:dbg(hello).
ok
2> hello:start().
hello world
** exception error: no match of right hand side value 3
     in function  hello:test/1
     in call from hello:start/0
4> (<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,start,0,1,5},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,start,0,1,6},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,start,0,1,7},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,start,0,1,8},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,start,0,1,9},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,start,0,1,10},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,start,0,1,11},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,test,1,1,16},1)
(<0.34.0>) returned from ets:update_counter/3 -> 1
(<0.34.0>) call ets:update_counter(cover_internal_data_table,{bump,hello,test,1,1,17},1)   %这里我们看到出错的行号
(<0.34.0>) returned from ets:update_counter/3 -> 1
3> 
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution

我们可以看到最后一次执行hello模块的行数是17.

Bingo!

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

从FTP模块学习先进的诊断技术(Erlang Trace机制)

April 12th, 2010 2 comments

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

本文链接地址: 从FTP模块学习先进的诊断技术(Erlang Trace机制)

我们开发好了一个软件的时候,通常是经过严格测试的,才分发给用户使用, 但是即使这样也不能保证用户的环境和我们的相同, 我们的软件还是会失败的. 问题是如何诊断这些问题.
通常的做法是写log,这是个很有效的方式. 但是写log要代码支持,而且会带来负面的性能影响. Erlang提供了强大的Trace机制, 帮助我们解决这个问题. OTP本身有很多模块利用了这个技术手段,我们从ftp模块学习下:

上代码:
lib/inets/src/ftp/ftp.erl

 771    %% Maybe activate dbg                                                                                                                                                                                  
 772    case key_search(debug, Options, disable) of
 773        trace ->
 774            dbg:tracer(),
 775            dbg:p(all, [call]),  %% 我们关心函数调用
 776            dbg:tpl(ftp, [{'_', [], [{return_trace}]}]), %%以及返回值
 777            dbg:tpl(ftp_response, [{'_', [], [{return_trace}]}]),
 778            dbg:tpl(ftp_progress, [{'_', [], [{return_trace}]}]);
 779        debug ->
 780            dbg:tracer(),
 781            dbg:p(all, [call]),
 782            dbg:tp(ftp, [{'_', [], [{return_trace}]}]),
 783            dbg:tp(ftp_response, [{'_', [], [{return_trace}]}]),
 784            dbg:tp(ftp_progress, [{'_', [], [{return_trace}]}]);
 785        _ ->
 786            %% Keep silent                                                                                                                                                                                 
 787            ok
 788    end,

我们可以在启动参数里面加上debug标志, 在需要的时候打开这些诊断功能!

现在我们演示下,代码片段从inets userguide来的, 用户名密码不用试验了, 我不会告诉你的, 呵呵:

root@ubuntu:~# erl
Erlang R14A (erts-5.8) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.8  (abort with ^G)
1> inets:start().  
ok
2> {ok,Pid} = inets:start(ftpc, [{host,"ftp.yufeng.info"},{debug,debug}])
2> .
(<0.45.0>) call ftp:handle_call({<0.31.0>,
 {open,ip_comm,
       [{host,"ftp.yufeng.info"},
        {progress,ignore},
        {timeout,60000},
        {ipfamily,inet},
        {port,21},
        {mode,passive}]}},{<0.31.0>,#Ref<0.0.0.45>},{state,undefined,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,undefined,undefined,inet,ignore})
(<0.45.0>) call ftp_progress:start_link(ignore)
(<0.45.0>) returned from ftp_progress:start_link/1 -> ignore
(<0.45.0>) returned from ftp:handle_call/3 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.45>},
                                                open,inet,ignore},
                                               59493}
(<0.45.0>) call ftp:handle_info({tcp,#Port<0.1086>,
     <<"220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\r\n220-You are user number 7 of 1000 allowed.\r\n220-Local time is now 02:33. Server port: 21.\r\n220-IPv6 connections are also welcome on this server.\r\n220 You will be disconnected after 15 minutes of inactivity.\r\n">>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.45>},
       open,inet,ignore})
(<0.45.0>) call ftp_response:parse_lines(<<"220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\r\n220-You are user number 7 of 1000 allowed.\r\n220-Local time is now 02:33. Server port: 21.\r\n220-IPv6 connections are also welcome on this server.\r\n220 You will be disconnected after 15 minutes of inactivity.\r\n">>,[],start)
(<0.45.0>) returned from ftp_response:parse_lines/3 -> {ok,
                                                        "220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\r\n220-You are user number 7 of 1000 allowed.\r\n220-Local time is now 02:33. Server port: 21.\r\n220-IPv6 connections are also welcome on this server.\r\n220 You will be disconnected after 15 minutes of inactivity.\r\n",
                                                        <<>>}
(<0.45.0>) call ftp_response:interpret("220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\r\n220-You are user number 7 of 1000 allowed.\r\n220-Local time is now 02:33. Server port: 21.\r\n220-IPv6 connections are also welcome on this server.\r\n220 You will be disconnected after 15 minutes of inactivity.\r\n")
{ok,<0.45.0>}
(<0.45.0>) returned from ftp_response:interpret/1 -> {pos_compl,
                                                      "---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\r\n220-You are user number 7 of 1000 allowed.\r\n220-Local time is now 02:33. Server port: 21.\r\n220-IPv6 connections are also welcome on this server.\r\n220 You will be disconnected after 15 minutes of inactivity.\r\n"}
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,undefined,undefined,
                                                inet,ignore}}
3> ftp:user(Pid, "username", "password").
(<0.31.0>) call ftp:user(<0.45.0>,"username","password")
(<0.45.0>) call ftp:handle_call({<0.31.0>,{user,"username","password"}},{<0.31.0>,#Ref<0.0.0.64>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,undefined,undefined,inet,ignore})
(<0.45.0>) returned from ftp:handle_call/3 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.64>},
                                                {handle_user,"password",[]},
                                                inet,ignore}}
(<0.45.0>) call ftp:handle_info({tcp,#Port<0.1086>,<<"331 User yufengin OK. Password required\r\n">>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.64>},
       {handle_user,"password",[]},
       inet,ignore})
(<0.45.0>) call ftp_response:parse_lines(<<"331 User yufengin OK. Password required\r\n">>,[],start)
(<0.45.0>) returned from ftp_response:parse_lines/3 -> {ok,
                                                        "331 User yufengin OK. Password required\r\n",
                                                        <<>>}
(<0.45.0>) call ftp_response:interpret("331 User yufengin OK. Password required\r\n")
(<0.45.0>) returned from ftp_response:interpret/1 -> {pos_interm,
                                                      " User yufengin OK. Password required\r\n"}
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.64>},
                                                {handle_user_passwd,[]},
                                                inet,ignore}}
(<0.45.0>) call ftp:handle_info({tcp,#Port<0.1086>,
     <<"230-User yufengin has group access to:  yufengin  \r\n230 OK. Current restricted directory is /\r\n">>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.64>},
       {handle_user_passwd,[]},
       inet,ignore})
(<0.45.0>) call ftp_response:parse_lines(<<"230-User yufengin has group access to:  yufengin  \r\n230 OK. Current restricted directory is /\r\n">>,[],start)
(<0.45.0>) returned from ftp_response:parse_lines/3 -> {ok,
                                                        "230-User yufengin has group access to:  yufengin  \r\n230 OK. Current restricted directory is /\r\n",
                                                        <<>>}
(<0.45.0>) call ftp_response:interpret("230-User yufengin has group access to:  yufengin  \r\n230 OK. Current restricted directory is /\r\n")
ok
(<0.45.0>) returned from ftp_response:interpret/1 -> {pos_compl,
                                                      "-User yufengin has group access to:  yufengin  \r\n230 OK. Current restricted directory is /\r\n"}
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,undefined,undefined,
                                                inet,ignore}}
(<0.31.0>) returned from ftp:user/3 -> ok
4> 
4>  ftp:pwd(Pid).
(<0.31.0>) call ftp:pwd(<0.45.0>)
(<0.45.0>) call ftp:handle_call({<0.31.0>,pwd},{<0.31.0>,#Ref<0.0.0.84>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,undefined,undefined,inet,ignore})
(<0.45.0>) returned from ftp:handle_call/3 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.84>},
                                                pwd,inet,ignore}}
(<0.45.0>) call ftp:handle_info({tcp,#Port<0.1086>,<<"257 \"/\" is your current location\r\n">>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.84>},
       pwd,inet,ignore})
(<0.45.0>) call ftp_response:parse_lines(<<"257 \"/\" is your current location\r\n">>,[],start)
(<0.45.0>) returned from ftp_response:parse_lines/3 -> {ok,
                                                        "257 \"/\" is your current location\r\n",
                                                        <<>>}
(<0.45.0>) call ftp_response:interpret("257 \"/\" is your current location\r\n")
{ok,"/"}
(<0.45.0>) returned from ftp_response:interpret/1 -> {pos_compl,
                                                      " \"/\" is your current location\r\n"}
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,undefined,undefined,
                                                inet,ignore}}
(<0.31.0>) returned from ftp:pwd/1 -> {ok,"/"}
7> ftp:recv(Pid, "favicon.ico").
(<0.31.0>) call ftp:recv(<0.45.0>,"favicon.ico")
(<0.45.0>) call ftp:handle_call({<0.31.0>,{recv,"favicon.ico","favicon.ico"}},{<0.31.0>,#Ref<0.0.0.120>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.112>},
       undefined,inet,ignore})
(<0.45.0>) returned from ftp:handle_call/3 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.120>},
                                                {setup_data_connection,
                                                 {recv_file,"favicon.ico",
                                                  {file_descriptor,prim_file,
                                                   {#Port<0.1087>,9}}}},
                                                inet,ignore}}
(<0.45.0>) call ftp:handle_info({tcp,#Port<0.1086>,
     <<"227 Entering Passive Mode (74,220,215,202,156,59)\r\n">>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,
    passive,60000,<<>>,
    {<<>>,[],start},
    <0.31.0>,
    {<0.31.0>,#Ref<0.0.0.120>},
    {setup_data_connection,
        {recv_file,"favicon.ico",
            {file_descriptor,prim_file,{#Port<0.1087>,9}}}},
    inet,ignore})
(<0.45.0>) call ftp_response:parse_lines(<<"227 Entering Passive Mode (74,220,215,202,156,59)\r\n">>,[],start)
(<0.45.0>) returned from ftp_response:parse_lines/3 -> {ok,
                                                        "227 Entering Passive Mode (74,220,215,202,156,59)\r\n",
                                                        <<>>}
(<0.45.0>) call ftp_response:interpret("227 Entering Passive Mode (74,220,215,202,156,59)\r\n")
(<0.45.0>) returned from ftp_response:interpret/1 -> {pos_compl,
                                                      " Entering Passive Mode (74,220,215,202,156,59)\r\n"}
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                #Port<0.1093>,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.120>},
                                                {recv_file,
                                                 {file_descriptor,prim_file,
                                                  {#Port<0.1087>,9}}},
                                                inet,ignore}}
(<0.45.0>) call ftp:handle_info({tcp,#Port<0.1086>,<<"150 Accepted data connection\r\n">>},{state,#Port<0.1086>,#Port<0.1093>,false,"/root",ftp_server_default,false,
       passive,60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.120>},
       {recv_file,{file_descriptor,prim_file,{#Port<0.1087>,9}}},
       inet,ignore})
(<0.45.0>) call ftp_response:parse_lines(<<"150 Accepted data connection\r\n">>,[],start)
(<0.45.0>) returned from ftp_response:parse_lines/3 -> {ok,
                                                        "150 Accepted data connection\r\n",
                                                        <<>>}
(<0.45.0>) call ftp_response:interpret("150 Accepted data connection\r\n")
(<0.45.0>) returned from ftp_response:interpret/1 -> {pos_prel,
                                                      " Accepted data connection\r\n"}
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                #Port<0.1093>,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.120>},
                                                {recv_file,
                                                 {file_descriptor,prim_file,
                                                  {#Port<0.1087>,9}}},
                                                inet,ignore}}
ok
8> (<0.45.0>) call ftp:handle_info({tcp,#Port<0.1093>,
     <<71,73,70,56,57,97,1,0,1,0,128,0,0,255,255,255,255,255,255,33,249,4,1,7,
       0,1,0,44,0,0,0,0,1,0,1,0,0,2,2,76,1,0,59>>},{state,#Port<0.1086>,#Port<0.1093>,false,"/root",ftp_server_default,false,
       passive,60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.120>},
       {recv_file,{file_descriptor,prim_file,{#Port<0.1087>,9}}},
       inet,ignore})
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                #Port<0.1093>,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.120>},
                                                {recv_file,
                                                 {file_descriptor,prim_file,
                                                  {#Port<0.1087>,9}}},
                                                inet,ignore}}
(<0.45.0>) call ftp:handle_info({tcp_closed,#Port<0.1093>},{state,#Port<0.1086>,#Port<0.1093>,false,"/root",ftp_server_default,false,
       passive,60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.120>},
       {recv_file,{file_descriptor,prim_file,{#Port<0.1087>,9}}},
       inet,ignore})
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,
                                                {<0.31.0>,#Ref<0.0.0.120>},
                                                {recv_file,
                                                 {file_descriptor,prim_file,
                                                  {#Port<0.1087>,9}}},
                                                inet,ignore}}
(<0.45.0>) call ftp:handle_info({tcp,#Port<0.1086>,
     <<"226-File successfully transferred\r\n226 0.020 seconds (measured here), 2.07 Kbytes per second\r\n">>},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,
       {<0.31.0>,#Ref<0.0.0.120>},
       {recv_file,{file_descriptor,prim_file,{#Port<0.1087>,9}}},
       inet,ignore})
(<0.45.0>) call ftp_response:parse_lines(<<"226-File successfully transferred\r\n226 0.020 seconds (measured here), 2.07 Kbytes per second\r\n">>,[],start)
(<0.45.0>) returned from ftp_response:parse_lines/3 -> {ok,
                                                        "226-File successfully transferred\r\n226 0.020 seconds (measured here), 2.07 Kbytes per second\r\n",
                                                        <<>>}
(<0.45.0>) call ftp_response:interpret("226-File successfully transferred\r\n226 0.020 seconds (measured here), 2.07 Kbytes per second\r\n")
(<0.45.0>) returned from ftp_response:interpret/1 -> {pos_compl,
                                                      "-File successfully transferred\r\n226 0.020 seconds (measured here), 2.07 Kbytes per second\r\n"}
(<0.45.0>) returned from ftp:handle_info/2 -> {noreply,
                                               {state,#Port<0.1086>,
                                                undefined,false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,undefined,undefined,
                                                inet,ignore}}
(<0.31.0>) returned from ftp:recv/2 -> ok

8> inets:stop(ftpc, Pid).
ok
9> (<0.31.0>) call ftp:stop_service(<0.45.0>)
(<0.31.0>) returned from ftp:stop_service/1 -> ok
(<0.45.0>) call ftp:handle_cast({<0.31.0>,close},{state,#Port<0.1086>,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,undefined,undefined,inet,ignore})
(<0.45.0>) returned from ftp:handle_cast/2 -> {stop,normal,
                                               {state,undefined,undefined,
                                                false,"/root",
                                                ftp_server_default,false,
                                                passive,60000,<<>>,
                                                {<<>>,[],start},
                                                <0.31.0>,undefined,undefined,
                                                inet,ignore}}
(<0.45.0>) call ftp:terminate(normal,{state,undefined,undefined,false,"/root",ftp_server_default,false,passive,
       60000,<<>>,
       {<<>>,[],start},
       <0.31.0>,undefined,undefined,inet,ignore})
(<0.45.0>) returned from ftp:terminate/2 -> ok
9> h().      
1: inets:start()
-> ok
2: {ok,Pid} =
       inets:start(ftpc, [{host,"ftp.yufeng.info"},{debug,debug}])
-> {ok,<0.45.0>}
3: ftp:user(Pid, "username", "password")
-> ok
4: ftp:pwd(Pid)
-> {ok,"/"}
5: ftp:cd(Pid, "public_html")
-> ok
6: ftp:lpwd(Pid)
-> {ok,"/root"}
7: ftp:recv(Pid, "favicon.ico")
-> ok
8: inets:stop(ftpc, Pid)
-> ok

Bingo! 我们非常的清楚了看到了整个系统交互的流程. 不废吹灰之力.

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

Categories: Erlang探索 Tags: , , , , ,

erlang的profile工具原理和优缺点

October 10th, 2009 Comments off

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

本文链接地址: erlang的profile工具原理和优缺点

erlang的tools application下包含了一系列的profile工具, 包括 eprof cprof fprof, 具体的使用可以参看文档和<< erlang effective guide>>.

我这里要说的是他们的工作原理。 这些模块的核心都是根据erlang的trace机制实现的。在模块执行的时候,trace机制会通知那个函数被调用 返回。根据这些信息就可以统计出来函数调用的频度,调用栈等。

但是利用这个机制会有严重的性能损失。因为每个函数调用都要发送一条trace信息,每个trace 信息会引起上下文切换 而且要耗费2-3的时间。这个对大型的系统是不可接受的。

所以知道这些原理以后, 我们在profile大型的系统的时候,我们可以在dbg模块的帮助下, 只收集我们感兴趣的东西,而且严格限定范围,避免对系统造成大的干扰,这样收集出来的东西才有意义。

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

Categories: Erlang探索 Tags: , , ,