1 %%%----------------------------------------------------------------------
3 %%% Author : Mats Cronqvist <etxmacr@avc386>
4 %%% Purpose : cpu time per pid
5 %%% Created : 28 Feb 2000 by Mats Cronqvist <etxmacr@avc386>
6 %%%----------------------------------------------------------------------
9 -author('etxmacr@avc386').
11 -export([go
/1, requires
/0, doc
/0]).
13 -record(state
, {tab
, in
= init
, gc
= init
, fd
= init
, prev
}).
15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16 requires() -> [{flags
, [garbage_collection
,procs
,running
]}, {tps
, []}].
17 doc() -> "populates the cpu time table. "
18 "not useful on its own. run from pan:perf".
21 %%%go([Msg, Line, Out, initial, Tab|_]) when atom(Tab) ->
22 %%% go([Msg, Line, Out, #state{tab = Tab}]);
23 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
24 go([Msg
, Line
, Out
, initial
|_
]) ->
26 go([Msg
, Line
, Out
, #state
{tab
= ?MODULE
}]);
27 go([end_of_trace
, Line
, Out
, State
|_
]) ->
29 go([Msg
, Line
, Out
, State
|_
]) ->
30 (handle(Msg
, State
))#state
{prev
= element(4,Msg
)}.
32 handle(Msg
, State
= #state
{tab
= Tab
, in
= In
, prev
= Prev
}) ->
35 ets_upd(Tab
, {file_driver
, in
}, 1),
36 State#state
{fd
= {Now
}};
37 {out
, P
, _
, Prev
} -> %early r7b emu behaviour
38 handle({out
, P
, 0, Prev
}, State
);
40 do_fd_out(Tab
, Now
, State
);
41 {in
, P
, _
, Now
} when tuple(State#state
.fd
) -> %early r7b emu behaviour
42 handle({in
, P
, 0, Now
}, State
);
43 {gc_start
, {Pid
, ID
}, Info
, Now
} ->
44 ets_upd(Tab
, {Pid
, gc
}, 1),
45 State#state
{gc
= {Pid
, Now
}};
46 {gc_end
, {Pid
, ID
}, Info
, Now
} ->
47 do_gc_out(Tab
, Pid
, Now
, State
);
48 {in
, {Pid
, ID
}, CurrF
, Now
} ->
49 ets_upd(Tab
, {Pid
, in
}, 1),
50 State#state
{in
= {Pid
, Now
}};
51 {out
, {Pid
, ID
}, CurrF
, Now
} ->
52 do_out(Tab
, Pid
, Now
, State
);
53 {exit, {Pid
, ID
}, Reason
, Now
} ->
55 {Pid
,_
} -> do_out(Tab
, Pid
, Now
, State
);
62 do_out(Tab
, Pid
, Now
, State
= #state
{in
= In
}) ->
65 Ntd
= ntdiff(Now
, InNow
),
66 ets_upd(Tab
, total
, Ntd
),
67 ets_upd(Tab
, {Pid
, cpu
}, Ntd
),
72 io:fwrite("~p - out_err~n~p~n", [?MODULE
, {Err
, Pid
, Now
, State
}]),
75 do_gc_out(Tab
, Pid
, Now
, State
= #state
{in
= In
, gc
= GC
}) ->
77 {{InPid
, _
}, {GcPid
, GcNow
}} ->
78 Ntd
= ntdiff(Now
, GcNow
),
79 ets_upd(Tab
, {InPid
, cpu
}, -Ntd
),
80 ets_upd(Tab
, {GcPid
, gcpu
}, Ntd
),
82 {_
, {GcPid
, GcNow
}} ->
83 Ntd
= ntdiff(Now
, GcNow
),
84 ets_upd(Tab
, total
, Ntd
),
85 ets_upd(Tab
, {Pid
, gcpu
}, Ntd
),
90 io:fwrite("~p - gc_out_err~n~p~n", [?MODULE
,{Err
, Pid
, Now
, State
}]),
93 do_fd_out(Tab
, Now
, State
= #state
{in
= In
, gc
= GC
, fd
= FD
}) ->
95 {{InPid
, _
}, {GcPid
, _
}, {FdNow
}} ->
96 Ntd
= ntdiff(Now
, FdNow
),
97 ets_upd(Tab
, total
, -Ntd
),
98 ets_upd(Tab
, {GcPid
, gcpu
}, -Ntd
),
99 ets_upd(Tab
, {file_driver
, cpu
}, Ntd
),
100 State#state
{fd
= no
};
101 {{InPid
, _
}, _
, {FdNow
}} ->
102 Ntd
= ntdiff(Now
, FdNow
),
103 ets_upd(Tab
, total
, -Ntd
),
104 ets_upd(Tab
, {InPid
, cpu
}, -Ntd
),
105 ets_upd(Tab
, {file_driver
, cpu
}, Ntd
),
106 State#state
{fd
= no
};
107 {_
, {GcPid
, _
}, {FdNow
}} ->
108 Ntd
= ntdiff(Now
, FdNow
),
109 ets_upd(Tab
, total
, -Ntd
),
110 ets_upd(Tab
, {GcPid
, gcpu
}, -Ntd
),
111 ets_upd(Tab
, {file_driver
, cpu
}, Ntd
),
112 State#state
{fd
= no
};
114 Ntd
= ntdiff(Now
, FdNow
),
115 ets_upd(Tab
, {file_driver
, cpu
}, Ntd
),
116 State#state
{fd
= no
};
119 io:fwrite("~p - fd_out_err~n~p~n", [?MODULE
, {Err
, Now
, State
}]),
122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123 ets_upd(Tab
, Key
, Inc
) ->
124 case catch ets:update_counter(Tab
, Key
, Inc
) of
125 {'EXIT', _
} -> ets:insert(Tab
, {Key
, Inc
});
129 ntdiff({MS
, S
, USo
}, {MS
, S
, USi
}) ->
131 ntdiff({MS
, So
, USo
}, {MS
, Si
, USi
}) ->
132 (USo
-USi
)+(So
-Si
)*1000000;
133 ntdiff({MSo
, So
, USo
}, {MSi
, Si
, USi
}) ->
134 (USo
-USi
)+(So
-Si
)*1000000+(MSo
-MSi
)*1000000000000.