Skip to content

Commit 6eb0361

Browse files
committed
Use processes_iterator() when available
This function (introduced in otp-28) doesn't take a global lock on process creation, and allows us to allocate less on systems with a high number of processes.
1 parent 0004afe commit 6eb0361

2 files changed

Lines changed: 51 additions & 17 deletions

File tree

src/recon.erl

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -316,16 +316,21 @@ proc_window(AttrName, Num, Time) ->
316316
%% for more details on refc binaries
317317
-spec bin_leak(pos_integer()) -> [proc_attrs()].
318318
bin_leak(N) ->
319-
Procs = recon_lib:sublist_top_n_attrs([
320-
try
321-
{ok, {_,Pre,Id}} = recon_lib:proc_attrs(binary, Pid),
322-
erlang:garbage_collect(Pid),
323-
{ok, {_,Post,_}} = recon_lib:proc_attrs(binary, Pid),
324-
{Pid, length(Pre) - length(Post), Id}
325-
catch
326-
_:_ -> {Pid, 0, []}
327-
end || Pid <- processes()
328-
], N),
319+
Procs = recon_lib:sublist_top_n_attrs(
320+
recon_lib:fold_processes(
321+
fun(Pid, Acc) ->
322+
Result = try
323+
{ok, {_,Pre,Id}} = recon_lib:proc_attrs(binary, Pid),
324+
erlang:garbage_collect(Pid),
325+
{ok, {_,Post,_}} = recon_lib:proc_attrs(binary, Pid),
326+
{Pid, length(Pre) - length(Post), Id}
327+
catch
328+
_:_ -> {Pid, 0, []}
329+
end,
330+
[Result | Acc]
331+
end,
332+
[]
333+
), N),
329334
[{Pid, -Val, Id} ||{Pid, Val, Id} <-Procs].
330335

331336
%% @doc Shorthand for `node_stats(N, Interval, fun(X,_) -> io:format("~p~n",[X]) end, nostate)'.

src/recon_lib.erl

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
term_to_port/1,
1414
time_map/5, time_fold/6,
1515
scheduler_usage_diff/2,
16-
sublist_top_n_attrs/2]).
16+
sublist_top_n_attrs/2,
17+
fold_processes/2]).
1718
%% private exports
1819
-export([binary_memory/1]).
1920

@@ -73,15 +74,45 @@ port_list(Attr, Val) ->
7374
[Port || Port <- erlang:ports(),
7475
{Attr, Val} =:= erlang:port_info(Port, Attr)].
7576

77+
%% @doc Fold over all processes, using efficient iterator when available (OTP 28+).
78+
-spec fold_processes(Fun, Acc0) -> Acc when
79+
Fun :: fun((pid(), Acc) -> Acc),
80+
Acc0 :: Acc,
81+
Acc :: term().
82+
fold_processes(Fun, Acc0) ->
83+
try
84+
Iter = erlang:processes_iterator(),
85+
fold_processes_iter(Fun, Acc0, Iter)
86+
catch
87+
error:undef ->
88+
lists:foldl(Fun, Acc0, processes())
89+
end.
90+
91+
fold_processes_iter(Fun, Acc, Iter) ->
92+
case erlang:processes_next(Iter) of
93+
{Pid, NewIter} ->
94+
NewAcc = Fun(Pid, Acc),
95+
fold_processes_iter(Fun, NewAcc, NewIter);
96+
none ->
97+
Acc
98+
end.
99+
76100
%% @doc Returns the attributes ({@link recon:proc_attrs()}) of
77101
%% all processes of the node, except the caller.
78102
-spec proc_attrs(term()) -> [recon:proc_attrs()].
79103
proc_attrs(AttrName) ->
80104
Self = self(),
81-
[Attrs || Pid <- processes(),
82-
Pid =/= Self,
83-
{ok, Attrs} <- [proc_attrs(AttrName, Pid)]
84-
].
105+
fold_processes(
106+
fun(Pid, Acc) when Pid =/= Self ->
107+
case proc_attrs(AttrName, Pid) of
108+
{ok, Attrs} -> [Attrs | Acc];
109+
{error, _} -> Acc
110+
end;
111+
(_, Acc) ->
112+
Acc
113+
end,
114+
[]
115+
).
85116

86117
%% @doc Returns the attributes of a given process. This form of attributes
87118
%% is standard for most comparison functions for processes in recon.
@@ -288,5 +319,3 @@ merge(H1, [E2|H2]) -> [E2, H1|H2].
288319
merge_pairs([]) -> [];
289320
merge_pairs([H]) -> H;
290321
merge_pairs([A, B|T]) -> merge(merge(A, B), merge_pairs(T)).
291-
292-

0 commit comments

Comments
 (0)