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