forked from massemanet/eper
-
Notifications
You must be signed in to change notification settings - Fork 15
/
sherk_tree.erl
92 lines (75 loc) · 2.7 KB
/
sherk_tree.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
%%%-------------------------------------------------------------------
%%% File : sherk_tree.erl
%%% Author : Mats Cronqvist <locmacr@mwlx084>
%%% Description :
%%%
%%% Created : 21 Aug 2006 by Mats Cronqvist <locmacr@mwlx084>
%%%-------------------------------------------------------------------
-module(sherk_tree).
-export([go/1]).
-import(lists,[foldl/3,reverse/1,sort/1,sort/2]).
-import(sherk,[to_str/1]).
-import(sherk_ets,[lup/2]).
-define(LOG(T), sherk:log(process_info(self()),T)).
go(procs) ->
Tot = lup(sherk_prof,{total,time}),
PTs = ets:match(sherk_prof,{{{pid,time},'$1'},'$2'}),
L = [{[reg(P),P],[garb(P),T]} || [P,T] <- PTs],
Pf = fun(Key,Data,Out) -> procsf(Tot,Key,Data,Out) end,
make_tree(L, Pf, fun sortpf/1);
go({callgraph,PidStr}) ->
case lup(sherk_prof,PidStr) of
[] -> [];
Pid -> callgraph(Pid)
end.
callgraph(Pid) ->
Tot = lup(sherk_prof,{{pid,time},Pid}),
L = ets:match(sherk_prof,{{{stack,time},Pid,'$1'},'$2'}),
LS = [{reverse(Stak),{T,called(Pid,Stak)}} || [Stak,T] <- L],
Gf = fun(Key,Data,Out) -> graphf(Tot,Key,Data,Out) end,
make_tree(LS, Gf, fun sortgf/1).
sortpf(L) ->
sort(fun({_,[_,_,_,T1],_},{_,[_,_,_,T2],_}) -> T2<T1 end,L).
procsf(_Tot,Pid,[Garb,Time],[]) when is_pid(Pid) ->
[to_str(Pid),1,Garb,Time];
procsf(_Tot,_Rg,[Garb,Time],[Tag,N,G,T]) ->
[Tag,N+1,G+Garb,T+Time];
procsf(_Tot,Reg,[Garb,Time],[]) ->
[to_str(Reg),1,Garb,Time].
sortgf(L) ->
sort(fun({_,[_,_,_,CT1],_},{_,[_,_,_,CT2],_}) -> CT2<CT1 end, L).
graphf(_Tot,MFA,{Time,Calls},[]) ->
[to_str(MFA),Calls,Time,Time];
graphf(_Tot,_,{Time,_},[Tag,Calls,T,CT]) ->
[Tag,Calls,T,CT+Time].
called(Pid,Stak) ->
lup(sherk_prof,{{stack,calls},Pid,Stak}).
reg(P) ->
case ets:lookup(sherk_scan,P) of
[] -> unknown;
[{P,{M,F,A}}] when is_list(A) -> {M,F,length(A)};
[{P,R}] -> R
end.
garb(Pid) ->
case lup(sherk_prof,{{pid,sched},Pid,gc_start}) of
[] -> 0;
V -> V
end.
%%%merg({R,T,P},[{Ti,R,TP}|Tail]) -> [{T+Ti,R,[{T,P}|TP]}|Tail];
%%%merg({R,T,P},O) -> [{T,R,[{T,P}]}|O].
%%%subtree(TP,T) ->
%%% [{[pct(Ti,T),garb(Pid),to_str(Pid)],[]} || {Ti,Pid} <- TP].
make_tree(L,DataF,SortF) ->
F = fun({Key,Data},A) -> tree_ins(Key,Data,DataF,SortF,A) end,
foldl(F, [], sort(L)).
%%% node() := {Key,Data,[nodes()]}
tree_ins([],_,_,_,[]) ->
[];
tree_ins([K|Ks],Data,Df,Sf,Tree) ->
case lists:keysearch(K,1,Tree) of
false ->
Sf([{K,Df(K,Data,[]),tree_ins(Ks,Data,Df,Sf,[])}|Tree]);
{value,{K,OData,OTree}} ->
Sf(krep(Tree,{K,Df(K,Data,OData),tree_ins(Ks,Data,Df,Sf,OTree)}))
end.
krep(List,El) -> lists:keyreplace(element(1,El),1,List,El).