1 -module(beam_stats_delta).
11 , of_context_switches/1
14 , of_process_info_reductions/2
18 { erlang_statistics :: ets:tid()
19 , erlang_process_info_reductions :: ets:tid()
35 { erlang_statistics = ets:new(beam_stats_delta_erlang_statistics, Options)
36 , erlang_process_info_reductions =
37 ets:new(beam_stats_delta_erlang_process_info_reductions, Options)
43 { erlang_statistics = TidErlangStatistics
44 , erlang_process_info_reductions = TidErlangProcessInfoReductions
47 true = ets:delete(TidErlangStatistics),
48 true = ets:delete(TidErlangProcessInfoReductions),
53 gc(?T{erlang_process_info_reductions=Table}=T) ->
57 ; FirstPid when is_pid(FirstPid) ->
61 -spec gc(t(), pid()) ->
63 gc(?T{erlang_process_info_reductions=Table}=T, Pid) ->
64 case beam_stats_source:erlang_is_process_alive(Pid)
66 ; false -> ets:delete(Table, Pid)
68 case ets:next(Table, Pid)
71 ; NextPid when is_pid(NextPid) ->
75 -spec of_context_switches(t()) ->
77 of_context_switches(?T{erlang_statistics=Table}) ->
78 Key = context_switches,
79 {Current, 0} = beam_stats_source:erlang_statistics(Key),
80 delta(Table, Key, Current).
83 { {io_bytes_in , non_neg_integer()}
84 , {io_bytes_out , non_neg_integer()}
86 of_io(?T{erlang_statistics=Table}) ->
89 , {output , CurrentOut}
90 } = beam_stats_source:erlang_statistics(Key),
91 DeltaIn = delta(Table, io_bytes_in , CurrentIn),
92 DeltaOut = delta(Table, io_bytes_out, CurrentOut),
93 { {io_bytes_in , DeltaIn}
94 , {io_bytes_out , DeltaOut}
97 % We can get between-calls-delta directly from erlang:statistics(reductions),
98 % but then if some other process also calls it - we'll get incorrect data on
100 % Managing deltas ourselves here, will at least reduce the possible callers to
101 % only those with knowledge of our table ID.
102 -spec of_reductions(t()) ->
104 of_reductions(?T{erlang_statistics=Table}) ->
106 {Current, _} = beam_stats_source:erlang_statistics(Key),
107 delta(Table, Key, Current).
109 -spec of_process_info_reductions(t(), pid()) ->
110 hope_option:t(non_neg_integer()).
111 of_process_info_reductions(?T{erlang_process_info_reductions=Table}, Pid) ->
112 case beam_stats_source:erlang_process_info(Pid, reductions)
115 ; {reductions, Current} ->
116 Delta = delta(Table, Pid, Current),
120 -spec delta(ets:tid(), Key, non_neg_integer()) ->
122 when Key :: atom() | pid().
123 delta(Table, Key, CurrentTotal) ->
124 PreviousTotalOpt = find(Table, Key),
125 PreviousTotal = hope_option:get(PreviousTotalOpt, 0),
126 save(Table, Key, CurrentTotal),
127 CurrentTotal - PreviousTotal.
129 -spec find(ets:tid(), term()) ->
130 hope_option:t(term()).
132 case ets:lookup(Table, K)
134 ; [{K, V}] -> {some, V}
137 -spec save(ets:tid(), term(), term()) ->
140 true = ets:insert(Table, {K, V}),