Skip to content

Commit

Permalink
Merge pull request #9342 from bjorng/bjorn/erts/booting/OTP-19450
Browse files Browse the repository at this point in the history
Limit peak memory use while loading code on small systems
  • Loading branch information
bjorng authored Jan 28, 2025
2 parents 1b2af94 + 1c80658 commit a0a606b
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 7 deletions.
Binary file modified erts/preloaded/ebin/erl_prim_loader.beam
Binary file not shown.
Binary file modified erts/preloaded/ebin/init.beam
Binary file not shown.
15 changes: 9 additions & 6 deletions erts/preloaded/src/erl_prim_loader.erl
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ loop(St0, Parent, Paths) ->
ok;
{Resp,#state{}=St1} ->
Pid ! {self(),Resp},
erlang:garbage_collect(),
loop(St1, Parent, Paths);
{_,State2,_} ->
exit({bad_state,Req,State2})
Expand Down Expand Up @@ -691,18 +692,20 @@ efile_gm_recv(N, Ref, Succ, Fail) ->
end.

efile_gm_spawn(ParentRef, Ms, Process, Paths) ->
efile_gm_spawn_1(0, Ms, ParentRef, Process, Paths).
S = erlang:system_info(schedulers_online),
MaxN = min(S + (S bsr 1), 32),
efile_gm_spawn_1(0, MaxN, Ms, ParentRef, Process, Paths).

efile_gm_spawn_1(N, Ms, ParentRef, Process, Paths) when N >= 32 ->
efile_gm_spawn_1(N, MaxN, Ms, ParentRef, Process, Paths) when N > MaxN ->
receive
{'DOWN',_,process,_,_} ->
efile_gm_spawn_1(N-1, Ms, ParentRef, Process, Paths)
efile_gm_spawn_1(N-1, MaxN, Ms, ParentRef, Process, Paths)
end;
efile_gm_spawn_1(N, [M|Ms], ParentRef, Process, Paths) ->
efile_gm_spawn_1(N, MaxN, [M|Ms], ParentRef, Process, Paths) ->
Get = fun() -> efile_gm_get(Paths, M, ParentRef, Process) end,
_ = spawn_monitor(Get),
efile_gm_spawn_1(N+1, Ms, ParentRef, Process, Paths);
efile_gm_spawn_1(_, [], _, _, _) ->
efile_gm_spawn_1(N+1, MaxN, Ms, ParentRef, Process, Paths);
efile_gm_spawn_1(_, _, [], _, _, _) ->
ok.

efile_gm_get(Paths, Mod, ParentRef, Process) ->
Expand Down
19 changes: 19 additions & 0 deletions erts/preloaded/src/init.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1359,6 +1359,18 @@ eval_script(What, #es{}) ->
load_modules(Mods0, Init) ->
Mods = [M || M <- Mods0, not erlang:module_loaded(M)],
F = prepare_loading_fun(),
case has_small_memory() of
true ->
%% Load one module at the time to reduce the peak memory
%% usage.
_ = [do_load_modules([M], F, Init) || M <- Mods],
ok;
false ->
%% Load the modules in parallel.
do_load_modules(Mods, F, Init)
end.

do_load_modules(Mods, F, Init) ->
case erl_prim_loader:get_modules(Mods, F) of
{ok,{Prep0,[]}} ->
Prep = [Code || {_,{prepared,Code,_}} <- Prep0],
Expand Down Expand Up @@ -1394,6 +1406,13 @@ prepare_loading_fun() ->
end
end.

has_small_memory() ->
%% Heuristic for small memory. If true, we'll try to preserve
%% memory by not loading code in parallel.
(erlang:system_info(wordsize) =:= 4 andalso
erlang:system_info(schedulers_online) =:= 1) orelse
erlang:system_info(debug_compiled).

make_path(Pa, Pz, Path, Vars) ->
append([Pa,append([fix_path(Path,Vars),Pz])]).

Expand Down
4 changes: 3 additions & 1 deletion lib/kernel/src/code.erl
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,9 @@ ensure_loaded(Mod) when is_atom(Mod) ->
call({load_error, Mod, Ref}),
Error;
Prepared ->
call({load_ok, Prepared, Mod, File, Ref})
Res = call({load_ok, Prepared, Mod, File, Ref}),
erlang:garbage_collect(),
Res
end
end;
embedded ->
Expand Down

0 comments on commit a0a606b

Please sign in to comment.