aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-12-16 14:50:56 +0100
committerBjörn Gustavsson <[email protected]>2015-12-16 15:52:26 +0100
commitaf9bfce55f0df03edaab638dcd3612c8478dfcc9 (patch)
tree9433741c63c6324b86faf7d9417f1a413d3d6aaf
parent471d2408de06f3c93507769ce0eb0a9f42c3d119 (diff)
downloadotp-af9bfce55f0df03edaab638dcd3612c8478dfcc9.tar.gz
otp-af9bfce55f0df03edaab638dcd3612c8478dfcc9.tar.bz2
otp-af9bfce55f0df03edaab638dcd3612c8478dfcc9.zip
Remove erl_prim_loader:get_files/2
erl_prim_loader:get_files/2 was an optimization introduced before the SMP emulator (that is, before R11). The idea was to use the async threads in the efile driver to read multiple BEAM files from the disk in parallel. In a modern computer with the SMP emulator, loading a BEAM module seems to be more time-consuming than reading it from disk. To optimize loading we would need to load several modules in parallel. We could modify get_files/2 so that it would support parallel loading, but it is cleaner to first remove get_files/2 and then (in a future commit), introduce new functions to support parallel loading.
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl76
-rw-r--r--erts/preloaded/src/init.erl51
2 files changed, 6 insertions, 121 deletions
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 07c439a990..a8d1e4df76 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -42,7 +42,7 @@
-include("inet_boot.hrl").
%% Public
--export([start/3, set_path/1, get_path/0, get_file/1, get_files/2,
+-export([start/3, set_path/1, get_path/0, get_file/1,
list_dir/1, read_file_info/1, read_link_info/1, get_cwd/0, get_cwd/1]).
%% Used by erl_boot_server
@@ -69,7 +69,6 @@
timeout :: timeout(), % idle timeout
%% Number of timeouts before archives are released
n_timeouts :: non_neg_integer(),
- multi_get = false :: boolean(),
prim_state :: prim_state()}). % state for efile code loader
-define(IDLE_TIMEOUT, 60000). %% tear inet connection after 1 minutes
@@ -162,16 +161,11 @@ start_it("efile", Id, Pid, _Hosts) ->
_ ->
init_ack(Pid)
end,
- MultiGet = case erlang:system_info(thread_pool_size) of
- 0 -> false;
- _ -> true
- end,
PS = prim_init(),
State = #state {loader = efile,
id = Id,
data = Port,
timeout = infinity,
- multi_get = MultiGet,
prim_state = PS},
loop(State, Pid, []).
@@ -198,20 +192,6 @@ get_file(File) when is_atom(File) ->
get_file(File) ->
check_file_result(get_file, File, request({get_file,File})).
--spec get_files([{atom(), string()}],
- fun((atom(),binary(),string()) -> 'ok' | {'error', atom()})) ->
- 'ok' | {'error', atom()}.
-get_files(ModFiles, Fun) ->
- case request({get_files,{ModFiles,Fun}}) of
- E = {error,_M} ->
- E;
- {error,Reason,M} ->
- check_file_result(get_files, M, {error,Reason}),
- {error,M};
- ok ->
- ok
- end.
-
-spec list_dir(Dir) -> {'ok', Filenames} | 'error' when
Dir :: string(),
Filenames :: [Filename :: string()].
@@ -344,8 +324,6 @@ handle_request(Req, Paths, St0) ->
{{ok,Paths},St0};
{get_file,File} ->
handle_get_file(St0, Paths, File);
- {get_files,{ModFiles,Fun}} ->
- handle_get_files(St0, ModFiles, Paths, Fun);
{list_dir,Dir} ->
handle_list_dir(St0, Dir);
{read_file_info,File} ->
@@ -365,11 +343,6 @@ handle_request(Req, Paths, St0) ->
ignore
end.
-handle_get_files(State = #state{multi_get = true}, ModFiles, Paths, Fun) ->
- ?SAFE2(efile_multi_get_file_from_port(State, ModFiles, Paths, Fun), State);
-handle_get_files(State, _ModFiles, _Paths, _Fun) -> % no multi get
- {{error,no_multi_get},State}.
-
handle_get_file(State = #state{loader = efile}, Paths, File) ->
?SAFE2(efile_get_file_from_port(State, File, Paths), State);
handle_get_file(State = #state{loader = inet}, Paths, File) ->
@@ -420,53 +393,6 @@ handle_timeout(State = #state{loader = inet}, Parent) ->
%%% Functions which handle efile as prim_loader (default).
%%% --------------------------------------------------------
-%%% Reading many files in parallel is an optimization.
-%%% See also comment in init.erl.
-
-%% -> {ok,State} | {{error,Module},State} | {{error,Reason,Module},State}
-efile_multi_get_file_from_port(State, ModFiles, Paths, Fun) ->
- Ref = make_ref(),
- %% More than 200 processes is no gain.
- Max = erlang:min(200, erlang:system_info(thread_pool_size)),
- efile_multi_get_file_from_port2(ModFiles, 0, Max, State, Paths, Fun, Ref, ok).
-
-efile_multi_get_file_from_port2([MF | MFs], Out, Max, State, Paths, Fun, Ref, Ret) when Out < Max ->
- Self = self(),
- _Pid = spawn(fun() -> efile_par_get_file(Ref, State, MF, Paths, Self, Fun) end),
- efile_multi_get_file_from_port2(MFs, Out+1, Max, State, Paths, Fun, Ref, Ret);
-efile_multi_get_file_from_port2(MFs, Out, Max, _State, Paths, Fun, Ref, Ret) when Out > 0 ->
- receive
- {Ref, ok, State1} ->
- efile_multi_get_file_from_port2(MFs, Out-1, Max, State1, Paths, Fun, Ref, Ret);
- {Ref, {error,_Mod} = Error, State1} ->
- efile_multi_get_file_from_port2(MFs, Out-1, Max, State1, Paths, Fun, Ref, Error);
- {Ref, MF, {error,emfile,State1}} ->
- %% Max can take negative values. Out cannot.
- efile_multi_get_file_from_port2([MF | MFs], Out-1, Max-1, State1, Paths, Fun, Ref, Ret);
- {Ref, {M,_F}, {error,Error,State1}} ->
- efile_multi_get_file_from_port2(MFs, Out-1, 0, State1, Paths, Fun, Ref, {error,Error,M})
- end;
-efile_multi_get_file_from_port2(_MFs, 0, _Max, State, _Paths, _Fun, _Ref, Ret) ->
- {Ret,State}.
-
-efile_par_get_file(Ref, State, {Mod,File} = MF, Paths, Pid, Fun) ->
- %% One port for each file read in "parallel":
- case prim_file:start() of
- {ok, Port} ->
- Port0 = State#state.data,
- State1 = State#state{data = Port},
- R = case efile_get_file_from_port(State1, File, Paths) of
- {{error,Reason},State2} ->
- {Ref,MF,{error,Reason,State2}};
- {{ok,BinFile,Full},State2} ->
- %% Fun(...) -> ok | {error,Mod}
- {Ref,Fun(Mod, BinFile, Full),State2#state{data=Port0}}
- end,
- prim_file:close(Port),
- Pid ! R;
- {error, Error} ->
- Pid ! {Ref,MF,{error,Error,State}}
- end.
%% -> {{ok,BinFile,File},State} | {{error,Reason},State}
efile_get_file_from_port(State, File, Paths) ->
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index cc30999ba5..b5c1d46e60 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -85,7 +85,6 @@
path_choice,
prim_load,
load_mode,
- par_load,
vars
}).
@@ -749,13 +748,11 @@ do_boot(Init,Flags,Start) ->
Deb = b2a(get_flag(init_debug, Flags, false)),
catch ?ON_LOAD_HANDLER ! {init_debug_flag,Deb},
BootVars = get_boot_vars(Root, Flags),
- ParLoad = Pgm =:= "efile" andalso
- erlang:system_info(thread_pool_size) > 0,
PathChoice = code_path_choice(),
Es = #es{init=Init,debug=Deb,path=Path,pa=Pa,pz=Pz,
path_choice=PathChoice,
- prim_load=true,load_mode=LoadMode,par_load=ParLoad,
+ prim_load=true,load_mode=LoadMode,
vars=BootVars},
eval_script(BootList, Es),
@@ -857,15 +854,12 @@ eval_script([{kernel_load_completed}|T], #es{load_mode=Mode}=Es0) ->
_ -> Es0#es{prim_load=false}
end,
eval_script(T, Es);
-eval_script([{primLoad,Mods}|T], #es{init=Init,prim_load=PrimLoad,
- par_load=Par}=Es)
+eval_script([{primLoad,Mods}|T], #es{prim_load=PrimLoad}=Es)
when is_list(Mods) ->
- case {PrimLoad,Par} of
- {true,true} ->
- par_load_modules(Mods, Init);
- {true,false} ->
+ case PrimLoad of
+ true ->
load_modules(Mods);
- {false,_} ->
+ false ->
%% Do not load now, code_server does that dynamically!
ok
end,
@@ -892,41 +886,6 @@ load_modules([Mod|Mods]) ->
load_modules([]) ->
ok.
-%%% An optimization: erl_prim_loader gets the chance of loading many
-%%% files in parallel, using threads. This will reduce the seek times,
-%%% and loaded code can be processed while other threads are waiting
-%%% for the disk. The optimization is not tried unless the loader is
-%%% "efile" and there is a non-empty pool of threads.
-%%%
-%%% Many threads are needed to get a good result, so it would be
-%%% beneficial to load several applications in parallel. However,
-%%% measurements show that the file system handles one directory at a
-%%% time, regardless if parallel threads are created for files on
-%%% several directories (a guess: writing the meta information when
-%%% the file was last read ('mtime'), forces the file system to sync
-%%% between directories).
-
-par_load_modules(Mods,Init) ->
- Ext = objfile_extension(),
- ModFiles = [{Mod,concat([Mod,Ext])} || Mod <- Mods,
- not erlang:module_loaded(Mod)],
- Self = self(),
- Fun = fun(Mod, BinCode, FullName) ->
- case catch load_mod_code(Mod, BinCode, FullName) of
- {ok, _} ->
- Init ! {Self,loaded,{Mod,FullName}},
- ok;
- _EXIT ->
- {error, Mod}
- end
- end,
- case erl_prim_loader:get_files(ModFiles, Fun) of
- ok ->
- ok;
- {error,Mod} ->
- exit({'cannot load',Mod,get_files})
- end.
-
make_path(Pa, Pz, Path, Vars) ->
append([Pa,append([fix_path(Path,Vars),Pz])]).