承接上文erlang火焰圖
dbg:p()方法分析
- dbg模塊是什么,有什么用?
- dbg:p()方法是什么?
- dbg:p()是怎么實現(xiàn)的?
dbg模塊是什么,有什么用
模塊dbg是基于文本跟蹤的一個工具,用它可以基于文本的方式跟蹤函數(shù)調(diào)用,進程,消息收發(fā),從而指導(dǎo)系統(tǒng)運行時的狀態(tài)。
dbg:p()方法是什么
dbg:p/1和dbg:p/2方法是用來開始跟蹤進程的。p/2有兩個入?yún)?,Item和Flags,第一個參數(shù)決定跟蹤誰,第二個參數(shù)決定如何跟蹤(收集哪些參數(shù))
-
Item含義如下:
- 如果Item是pid(),就指定跟蹤這個進程;
- 如果Item是all,追蹤所有的進程包括以后新建立的進程;
- 如果Item是new,追蹤所有新建立的進程;
- 其它更多請參考文檔
-
Flags
- s(send),跟蹤進程發(fā)送的消息
- r(receive),跟蹤進程接受的消息
- 其它更多參考文檔
調(diào)用dbg:p方法之前,需要首先dbg:tracer/0或者dbg:tracer/2啟動一個收集消息的進程,然后跟蹤的消息發(fā)送到這個進程即可。
dbg:p()方法如何實現(xiàn)
代碼不多,直接上源碼分析。
- 首先封裝
<pre>
p(Pid) ->
p(Pid, [m]).
p(Pid, Flags) when is_atom(Flags) ->
p(Pid, [Flags]);
p(Pid, Flags) ->
req({p,Pid,Flags}).
</pre>
可以看出,最后調(diào)用到req()方法。 - req方法
<pre>
req(R) ->
P = ensure(), % The pid or perhaps the name of the server
Mref = erlang:monitor(process, P),
catch P ! {self(), R}, % May crash if P = atom() and server died
receive
{'DOWN', Mref, _, _, _} -> % If server died
exit(dbg_server_crash);
{dbg, Reply} ->
erlang:demonitor(Mref, [flush]),
Reply
end.
</pre>
P ! {self(), R}這里就是向dbg收集消息的server發(fā)送消息,R開頭的tag就是p。
ensure()方法保證又一個dbg收集消息的server,沒有就啟動一個。ensure()方法相關(guān)如下
<pre>
%%% Server implementation.
start() ->
start(no_tracer).
start(TracerFun) ->
S = self(),
case whereis(dbg) of
undefined ->
Dbg = spawn(fun() -> init(S) end),
receive {Dbg,started} -> ok end,
case TracerFun of
no_tracer ->
{ok, Dbg};
Fun when is_function(Fun) ->
req({tracer,TracerFun})
end;
Pid when is_pid(Pid), is_function(TracerFun) ->
req({tracer,TracerFun})
end.
init(Parent) ->
process_flag(trap_exit, true),
register(dbg, self()),
Parent ! {self(),started},
loop({[],[]},[]).
</pre>
- 看看dbg server是如何處理p消息的
<pre>
loop({C,T}=SurviveLinks, Table) ->
receive
......
{From,{p,Pid,Flags}} ->
reply(From, trace_process(Pid, Flags)),
loop(SurviveLinks, Table);
......
</pre>
看看trace_process(Pid,Flags),實際上最后調(diào)用的如下
<pre>
trac(Node, {_Relay, Tracer}, AtomPid, How, Flags) ->
case rpc:call(Node, ?MODULE, erlang_trace,
[AtomPid, How, [{tracer, Tracer} | Flags]]) of
N when is_integer(N) ->
{matched, Node, N};
{badrpc,Reason} ->
{matched, Node, 0, Reason};
Else ->
{matched, Node, 0, Else}
end.
</pre>
其實調(diào)用的是erlang_trace()方法
- erlang:trace(PidSpec, How, FlagList) -> integer()
第一個參數(shù)決定跟蹤對象,How就是true和false,表示是否進行跟蹤,F(xiàn)lagList就是跟蹤的信息。FlagList加上{tracer, Tracer},表示把跟蹤信息發(fā)送給Tracer。消息類似
<pre>
{trace, Pid, 'receive', Msg}
</pre>
更多參考文檔。
其他:
凡事涉及到系統(tǒng)trace,有兩個概念:cpu time和wall_clock_time, 它們的概念和區(qū)別在這里
Wall-clock_time,請自行科學(xué)上網(wǎng)。具體說來,就是這段話
In computing, wall-clock time can also mean the actual time by a computer to complete a task.
It is the sum of three terms: CPU time, I/O time, and the communication channel delay (e.g. if data are scattered on multiple machines). In contrast to CPU time, which measures only the time during which the processor is actively working on a certain task, wall time measures the total time for the process to complete. The difference between the two consists of time that passes due to programmed delays or waiting for resources to become available.