Collect reductions per process.
[beam_stats.git] / src / beam_stats_delta.erl
CommitLineData
b2c364fd
SK
1-module(beam_stats_delta).
2
3-export_type(
4 [ t/0
5 ]).
6
7-export(
8 [ start/0
9 , stop/1
10 , of_context_switches/1
11 , of_io/1
11e1cb97 12 , of_reductions/1
7dbc59b6 13 , of_process_info_reductions/2
b2c364fd
SK
14 ]).
15
16-record(?MODULE,
17 { erlang_statistics :: ets:tid()
7dbc59b6 18 , erlang_process_info_reductions :: ets:tid()
b2c364fd
SK
19 }).
20
21-define(T, #?MODULE).
22
23-opaque t() ::
24 ?T{}.
25
26-spec start() ->
27 t().
28start() ->
29 Options =
30 [ set
31 , public
32 ],
33 ?T
34 { erlang_statistics = ets:new(beam_stats_delta_erlang_statistics, Options)
7dbc59b6
SK
35 , erlang_process_info_reductions =
36 ets:new(beam_stats_delta_erlang_process_info_reductions, Options)
b2c364fd
SK
37 }.
38
39-spec stop(t()) ->
40 {}.
41stop(?T
42 { erlang_statistics = TidErlangStatistics
7dbc59b6 43 , erlang_process_info_reductions = TidErlangProcessInfoReductions
b2c364fd
SK
44 }
45) ->
46 true = ets:delete(TidErlangStatistics),
7dbc59b6 47 true = ets:delete(TidErlangProcessInfoReductions),
b2c364fd
SK
48 {}.
49
50-spec of_context_switches(t()) ->
51 non_neg_integer().
52of_context_switches(?T{erlang_statistics=Table}) ->
53 Key = context_switches,
54 {Current, 0} = beam_stats_source:erlang_statistics(Key),
55 delta(Table, Key, Current).
56
57-spec of_io(t()) ->
58 { {io_bytes_in , non_neg_integer()}
59 , {io_bytes_out , non_neg_integer()}
60 }.
61of_io(?T{erlang_statistics=Table}) ->
62 Key = io,
63 { {input , CurrentIn}
64 , {output , CurrentOut}
65 } = beam_stats_source:erlang_statistics(Key),
66 DeltaIn = delta(Table, io_bytes_in , CurrentIn),
67 DeltaOut = delta(Table, io_bytes_out, CurrentOut),
68 { {io_bytes_in , DeltaIn}
69 , {io_bytes_out , DeltaOut}
70 }.
71
11e1cb97
SK
72% We can get between-calls-delta directly from erlang:statistics(reductions),
73% but then if some other process also calls it - we'll get incorrect data on
74% the next call.
75% Managing deltas ourselves here, will at least reduce the possible callers to
76% only those with knowledge of our table ID.
77-spec of_reductions(t()) ->
78 non_neg_integer().
79of_reductions(?T{erlang_statistics=Table}) ->
80 Key = reductions,
81 {Current, _} = beam_stats_source:erlang_statistics(Key),
82 delta(Table, Key, Current).
83
7dbc59b6
SK
84-spec of_process_info_reductions(t(), pid()) ->
85 hope_option:t(non_neg_integer()).
86of_process_info_reductions(?T{erlang_process_info_reductions=Table}, Pid) ->
87 case beam_stats_source:erlang_process_info(Pid, reductions)
88 of undefined ->
89 none
90 ; {reductions, Current} ->
91 Delta = delta(Table, Pid, Current),
92 {some, Delta}
93 end.
94
95-spec delta(ets:tid(), Key, non_neg_integer()) ->
96 non_neg_integer()
97 when Key :: atom() | pid().
b2c364fd
SK
98delta(Table, Key, CurrentTotal) ->
99 PreviousTotalOpt = find(Table, Key),
100 PreviousTotal = hope_option:get(PreviousTotalOpt, 0),
101 save(Table, Key, CurrentTotal),
102 CurrentTotal - PreviousTotal.
103
104-spec find(ets:tid(), term()) ->
105 hope_option:t(term()).
106find(Table, K) ->
107 case ets:lookup(Table, K)
108 of [] -> none
109 ; [{K, V}] -> {some, V}
110 end.
111
112-spec save(ets:tid(), term(), term()) ->
113 {}.
114save(Table, K, V) ->
115 true = ets:insert(Table, {K, V}),
116 {}.
This page took 0.023965 seconds and 4 git commands to generate.