aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-12-11 16:25:34 +0100
committerBjörn Gustavsson <[email protected]>2015-12-14 15:57:30 +0100
commit3131a94b5d2ce2b95aa0efb99c767e3658f24550 (patch)
tree48dfccb00163154532f81a5d638b3262af4600b1
parent3ecefb19e555e52e35c8f2c5178c72f165c4a7ce (diff)
downloadotp-3131a94b5d2ce2b95aa0efb99c767e3658f24550.tar.gz
otp-3131a94b5d2ce2b95aa0efb99c767e3658f24550.tar.bz2
otp-3131a94b5d2ce2b95aa0efb99c767e3658f24550.zip
Remove the code path cache in the code server
In practice, it does not seem that code path cache can improve performance. Looking for any file that is not found will cause the cache to be rebuilt, which will negate any gain of using the cache.
-rw-r--r--lib/kernel/doc/src/code.xml36
-rw-r--r--lib/kernel/src/code.erl45
-rw-r--r--lib/kernel/src/code_server.erl170
-rw-r--r--lib/kernel/test/code_SUITE.erl172
-rw-r--r--lib/stdlib/src/otp_internal.erl2
5 files changed, 47 insertions, 378 deletions
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index eb0f4b7a06..acc39145e2 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -101,30 +101,6 @@
</section>
<section>
- <title>Code Path Cache</title>
- <p>The code server incorporates a code path cache. The cache
- functionality is disabled by default. To activate it, start
- the emulator with the command line flag <c>-code_path_cache</c>
- or call <c>code:rehash()</c>. When the cache is created (or
- updated), the code server searches for modules in the code path
- directories. This may take some time if the the code path is long.
- After the cache creation, the time for loading modules in a large
- system (one with a large directory structure) is significantly
- reduced compared to having the cache disabled. The code server
- is able to look up the location of a module from the cache in
- constant time instead of having to search through the code path
- directories.</p>
- <p>Application resource files (<c>.app</c> files) are also stored
- in the code path cache. This feature is used by the application
- controller (see
- <seealso marker="application">application(3)</seealso>) to load
- applications efficiently in large systems.</p>
- <p>Note that when the code path cache is created (or updated), any
- relative directory names in the code path are converted to
- absolute.</p>
- </section>
-
- <section>
<title>Loading of Code From Archive Files</title>
<warning><p>The support for loading of code from archive files is
@@ -700,13 +676,6 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="rehash" arity="0"/>
- <fsummary>Rehash or create code path cache</fsummary>
- <desc>
- <p>This function creates or rehashes the code path cache.</p>
- </desc>
- </func>
- <func>
<name name="where_is_file" arity="1"/>
<fsummary>Full name of a file located in the code path</fsummary>
<desc>
@@ -714,10 +683,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
arbitrary type. If found, the full name is returned.
<c>non_existing</c> is returned if the file cannot be found.
The function can be useful, for example, to locate
- application resource files. If the code path cache is used,
- the code server will efficiently read the full name from
- the cache, provided that <c><anno>Filename</anno></c> is an object code
- file or an <c>.app</c> file.</p>
+ application resource files.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 352c02562b..ae28c97b47 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -68,6 +68,8 @@
clash/0,
get_mode/0]).
+-deprecated({rehash,0,next_major_release}).
+
-export_type([load_error_rsn/0, load_ret/0]).
-include_lib("kernel/include/file.hrl").
@@ -293,7 +295,9 @@ replace_path(Name, Dir) when (is_atom(Name) orelse is_list(Name)),
call({replace_path,Name,Dir}).
-spec rehash() -> 'ok'.
-rehash() -> call(rehash).
+rehash() ->
+ cache_warning(),
+ ok.
-spec get_mode() -> 'embedded' | 'interactive'.
get_mode() -> call(get_mode).
@@ -322,6 +326,7 @@ start_link(Flags) ->
%%-----------------------------------------------------------------
do_start(Flags) ->
+ maybe_warn_for_cache(),
load_code_server_prerequisites(),
Mode = get_mode(Flags),
@@ -452,30 +457,14 @@ which(File, Base, [Directory|Tail]) ->
Filename :: file:filename(),
Absname :: file:filename().
where_is_file(File) when is_list(File) ->
- case call({is_cached,File}) of
- no ->
- Path = get_path(),
- which(File, ".", Path);
- Dir ->
- filename:join(Dir, File)
- end.
+ Path = get_path(),
+ which(File, ".", Path).
-spec where_is_file(Path :: file:filename(), Filename :: file:filename()) ->
file:filename() | 'non_existing'.
where_is_file(Path, File) when is_list(Path), is_list(File) ->
- CodePath = get_path(),
- if
- Path =:= CodePath ->
- case call({is_cached, File}) of
- no ->
- which(File, ".", Path);
- Dir ->
- filename:join(Dir, File)
- end;
- true ->
- which(File, ".", Path)
- end.
+ which(File, ".", Path).
-spec set_primary_archive(ArchiveFile :: file:filename(),
ArchiveBin :: binary(),
@@ -553,6 +542,22 @@ has_ext(Ext, Extlen, File) ->
end.
%%%
+%%% Warning for deprecated code path cache.
+%%%
+
+maybe_warn_for_cache() ->
+ case init:get_argument(code_path_cache) of
+ {ok, _} ->
+ cache_warning();
+ error ->
+ ok
+ end.
+
+cache_warning() ->
+ W = "The code path cache functionality has been removed",
+ error_logger:warning_report(W).
+
+%%%
%%% Silently load native code for all modules loaded so far.
%%%
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 68dd21b1d7..4361bb7b60 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -40,7 +40,6 @@
path,
moddb,
namedb,
- cache = no_cache,
mode = interactive,
on_load = []}).
-type state() :: #state{}.
@@ -89,19 +88,11 @@ init(Ref, Parent, [Root,Mode0]) ->
end,
Path = add_loader_path(IPath, Mode),
- State0 = #state{root = Root,
- path = Path,
- moddb = Db,
- namedb = init_namedb(Path),
- mode = Mode},
-
- State =
- case init:get_argument(code_path_cache) of
- {ok, _} ->
- create_cache(State0);
- error ->
- State0
- end,
+ State = #state{root = Root,
+ path = Path,
+ moddb = Db,
+ namedb = init_namedb(Path),
+ mode = Mode},
put(?ANY_NATIVE_CODE_LOADED, false),
@@ -264,50 +255,29 @@ handle_call({load_file,Mod}, Caller, St) ->
end;
handle_call({add_path,Where,Dir0}, {_From,_Tag},
- #state{cache=Cache0,namedb=Namedb,path=Path0}=S) ->
- case Cache0 of
- no_cache ->
- {Resp,Path} = add_path(Where, Dir0, Path0, Namedb),
- {reply,Resp,S#state{path=Path}};
- _ ->
- Dir = absname(Dir0), %% Cache always expands the path
- {Resp,Path} = add_path(Where, Dir, Path0, Namedb),
- Cache = update_cache([Dir], Where, Cache0),
- {reply,Resp,S#state{path=Path,cache=Cache}}
- end;
+ #state{namedb=Namedb,path=Path0}=S) ->
+ {Resp,Path} = add_path(Where, Dir0, Path0, Namedb),
+ {reply,Resp,S#state{path=Path}};
handle_call({add_paths,Where,Dirs0}, {_From,_Tag},
- #state{cache=Cache0,namedb=Namedb,path=Path0}=S) ->
- case Cache0 of
- no_cache ->
- {Resp,Path} = add_paths(Where, Dirs0, Path0, Namedb),
- {reply,Resp,S#state{path=Path}};
- _ ->
- %% Cache always expands the path
- Dirs = [absname(Dir) || Dir <- Dirs0],
- {Resp,Path} = add_paths(Where, Dirs, Path0, Namedb),
- Cache=update_cache(Dirs,Where,Cache0),
- {reply,Resp,S#state{cache=Cache,path=Path}}
- end;
+ #state{namedb=Namedb,path=Path0}=S) ->
+ {Resp,Path} = add_paths(Where, Dirs0, Path0, Namedb),
+ {reply,Resp,S#state{path=Path}};
handle_call({set_path,PathList}, {_From,_Tag},
#state{path=Path0,namedb=Namedb}=S) ->
{Resp,Path,NewDb} = set_path(PathList, Path0, Namedb),
- {reply,Resp,rehash_cache(S#state{path=Path,namedb=NewDb})};
+ {reply,Resp,S#state{path=Path,namedb=NewDb}};
handle_call({del_path,Name}, {_From,_Tag},
#state{path=Path0,namedb=Namedb}=S) ->
{Resp,Path} = del_path(Name, Path0, Namedb),
- {reply,Resp,rehash_cache(S#state{path=Path})};
+ {reply,Resp,S#state{path=Path}};
handle_call({replace_path,Name,Dir}, {_From,_Tag},
#state{path=Path0,namedb=Namedb}=S) ->
{Resp,Path} = replace_path(Name, Dir, Path0, Namedb),
- {reply,Resp,rehash_cache(S#state{path=Path})};
-
-handle_call(rehash, {_From,_Tag}, S0) ->
- S = create_cache(S0),
- {reply,ok,S};
+ {reply,Resp,S#state{path=Path}};
handle_call(get_path, {_From,_Tag}, S) ->
{reply,S#state.path,S};
@@ -398,9 +368,6 @@ handle_call({is_sticky, Mod}, {_From,_Tag}, S) ->
handle_call(stop,{_From,_Tag}, S) ->
{stop,normal,stopped,S};
-handle_call({is_cached,_File}, {_From,_Tag}, S=#state{cache=no_cache}) ->
- {reply, no, S};
-
handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From,_Tag}, S=#state{mode=Mode}) ->
case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) of
{ok, Files} ->
@@ -409,26 +376,6 @@ handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From
{reply, Error, S}
end;
-handle_call({is_cached,File}, {_From,_Tag}, S=#state{cache=Cache}) ->
- ObjExt = objfile_extension(),
- Ext = filename:extension(File),
- Type = case Ext of
- ObjExt -> obj;
- ".app" -> app;
- _ -> undef
- end,
- if Type =:= undef ->
- {reply, no, S};
- true ->
- Key = {Type,list_to_atom(filename:rootname(File, Ext))},
- case ets:lookup(Cache, Key) of
- [] ->
- {reply, no, S};
- [{Key,Dir}] ->
- {reply, Dir, S}
- end
- end;
-
handle_call(get_mode, {_From,_Tag}, S=#state{mode=Mode}) ->
{reply, Mode, S};
@@ -448,69 +395,6 @@ do_mod_call(Action, Module, Error, St) ->
end.
%% --------------------------------------------------------------
-%% Cache functions
-%% --------------------------------------------------------------
-
-create_cache(St = #state{cache = no_cache}) ->
- Cache = ets:new(code_cache, [protected]),
- rehash_cache(Cache, St);
-create_cache(St) ->
- rehash_cache(St).
-
-rehash_cache(St = #state{cache = no_cache}) ->
- St;
-rehash_cache(St = #state{cache = OldCache}) ->
- ets:delete(OldCache),
- Cache = ets:new(code_cache, [protected]),
- rehash_cache(Cache, St).
-
-rehash_cache(Cache, St = #state{path = Path}) ->
- Exts = [{obj,objfile_extension()}, {app,".app"}],
- {Cache,NewPath} = locate_mods(lists:reverse(Path), first, Exts, Cache, []),
- St#state{cache = Cache, path=NewPath}.
-
-update_cache(Dirs, Where, Cache0) ->
- Exts = [{obj,objfile_extension()}, {app,".app"}],
- {Cache, _} = locate_mods(Dirs, Where, Exts, Cache0, []),
- Cache.
-
-locate_mods([Dir0|Path], Where, Exts, Cache, Acc) ->
- Dir = absname(Dir0), %% Cache always expands the path
- case erl_prim_loader:list_dir(Dir) of
- {ok, Files} ->
- Cache = filter_mods(Files, Where, Exts, Dir, Cache),
- locate_mods(Path, Where, Exts, Cache, [Dir|Acc]);
- error ->
- locate_mods(Path, Where, Exts, Cache, Acc)
- end;
-locate_mods([], _, _, Cache, Path) ->
- {Cache,Path}.
-
-filter_mods([File|Rest], Where, Exts, Dir, Cache) ->
- Ext = filename:extension(File),
- Root = list_to_atom(filename:rootname(File, Ext)),
- case lists:keyfind(Ext, 2, Exts) of
- {Type, _} ->
- Key = {Type,Root},
- case Where of
- first ->
- true = ets:insert(Cache, {Key,Dir});
- last ->
- case ets:lookup(Cache, Key) of
- [] ->
- true = ets:insert(Cache, {Key,Dir});
- _ ->
- ignore
- end
- end;
- false ->
- ok
- end,
- filter_mods(Rest, Where, Exts, Dir, Cache);
-filter_mods([], _, _, _, Cache) ->
- Cache.
-
-%% --------------------------------------------------------------
%% Path handling functions.
%% --------------------------------------------------------------
@@ -1238,16 +1122,6 @@ load_abs(File, Mod0, Caller, St) ->
{reply,{error,nofile},St}
end.
-try_load_module(Mod, Dir, Caller, St) ->
- File = filename:append(Dir, to_list(Mod) ++
- objfile_extension()),
- case erl_prim_loader:get_file(File) of
- error ->
- {reply,error,St};
- {ok,Binary,FName} ->
- try_load_module(absname(FName), Mod, Binary, Caller, St)
- end.
-
try_load_module(File, Mod, Bin, {From,_}=Caller, St0) ->
M = to_atom(Mod),
case pending_on_load(M, From, St0) of
@@ -1345,26 +1219,12 @@ load_file(Mod0, {From,_}=Caller, St0) ->
{yes,St} -> {noreply,St}
end.
-load_file_1(Mod, Caller, #state{path=Path,cache=no_cache}=St) ->
+load_file_1(Mod, Caller, #state{path=Path}=St) ->
case mod_to_bin(Path, Mod) of
error ->
{reply,{error,nofile},St};
{Mod,Binary,File} ->
try_load_module(File, Mod, Binary, Caller, St)
- end;
-load_file_1(Mod, Caller, #state{cache=Cache}=St0) ->
- Key = {obj,Mod},
- case ets:lookup(Cache, Key) of
- [] ->
- St = rehash_cache(St0),
- case ets:lookup(St#state.cache, Key) of
- [] ->
- {reply,{error,nofile},St};
- [{Key,Dir}] ->
- try_load_module(Mod, Dir, Caller, St)
- end;
- [{Key,Dir}] ->
- try_load_module(Mod, Dir, Caller, St0)
end.
mod_to_bin([Dir|Tail], Mod) ->
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index ef5303defd..dfcb20d594 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -30,8 +30,7 @@
upgrade/1,
sticky_dir/1, pa_pz_option/1, add_del_path/1,
dir_disappeared/1, ext_mod_dep/1, clash/1,
- load_cached/1, start_node_with_cache/1, add_and_rehash/1,
- where_is_file_cached/1, where_is_file_no_cache/1,
+ where_is_file/1,
purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1,
code_archive/1, code_archive2/1, on_load/1, on_load_binary/1,
on_load_embedded/1, on_load_errors/1, big_boot_embedded/1,
@@ -56,9 +55,8 @@ all() ->
load_binary, dir_req, object_code, set_path_file,
upgrade,
sticky_dir, pa_pz_option, add_del_path, dir_disappeared,
- ext_mod_dep, clash, load_cached, start_node_with_cache,
- add_and_rehash, where_is_file_no_cache,
- where_is_file_cached, purge_stacktrace, mult_lib_roots,
+ ext_mod_dep, clash, where_is_file,
+ purge_stacktrace, mult_lib_roots,
bad_erl_libs, code_archive, code_archive2, on_load,
on_load_binary, on_load_embedded, on_load_errors,
big_boot_embedded, native_early_modules, get_mode].
@@ -904,140 +902,7 @@ uniq([H|T],A) ->
uniq(T,[H|A]).
-load_cached(suite) ->
- [];
-load_cached(doc) ->
- [];
-load_cached(Config) when is_list(Config) ->
- Priv = ?config(priv_dir, Config),
- WD = filename:dirname(code:which(?MODULE)),
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-pa \"" ++ WD ++ "\""},
- {erl, [this]}]),
- CCTabCreated = fun(Tab) ->
- case ets:info(Tab, name) of
- code_cache -> true;
- _ -> false
- end
- end,
- Tabs = rpc:call(Node, ets, all, []),
- case rpc:call(Node, lists, any, [CCTabCreated,Tabs]) of
- true ->
- ?t:stop_node(Node),
- ?t:fail("Code cache should not be active!");
- false ->
- ok
- end,
- rpc:call(Node, code, del_path, [Priv]),
- rpc:call(Node, code, add_pathz, [Priv]),
-
- FullModName = Priv ++ "/code_cache_test",
- {ok,Dev} = file:open(FullModName ++ ".erl", [write]),
- io:format(Dev, "-module(code_cache_test). -export([a/0]). a() -> ok.~n", []),
- ok = file:close(Dev),
- {ok,code_cache_test} = compile:file(FullModName, [{outdir,Priv}]),
-
- F = fun load_loop/2,
- N = 1000,
- {T0,T1} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]),
- TNoCache = now_diff(T1, T0),
- rpc:call(Node, code, rehash, []),
- {T2,T3} = rpc:call(Node, erlang, apply, [F, [N,code_cache_test]]),
- TCache = now_diff(T3, T2),
- AvgNoCache = TNoCache/N,
- AvgCache = TCache/N,
- io:format("Avg. load time (no_cache/cache): ~w/~w~n", [AvgNoCache,AvgCache]),
- ?t:stop_node(Node),
- if AvgNoCache =< AvgCache ->
- ?t:fail("Cache not working properly.");
- true ->
- ok
- end.
-
-load_loop(N, M) ->
- load_loop(N, M, now()).
-load_loop(0, _M, T0) ->
- {T0,now()};
-load_loop(N, M, T0) ->
- code:load_file(M),
- code:delete(M),
- code:purge(M),
- load_loop(N-1, M, T0).
-
-now_diff({A2, B2, C2}, {A1, B1, C1}) ->
- ((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1.
-
-start_node_with_cache(suite) ->
- [];
-start_node_with_cache(doc) ->
- [];
-start_node_with_cache(Config) when is_list(Config) ->
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-code_path_cache"},
- {erl, [this]}]),
- Tabs = rpc:call(Node, ets, all, []),
- io:format("Tabs: ~w~n", [Tabs]),
- CCTabCreated = fun(Tab) ->
- case rpc:call(Node, ets, info, [Tab,name]) of
- code_cache -> true;
- _ -> false
- end
- end,
- true = lists:any(CCTabCreated, Tabs),
- ?t:stop_node(Node),
- ok.
-
-add_and_rehash(suite) ->
- [];
-add_and_rehash(doc) ->
- [];
-add_and_rehash(Config) when is_list(Config) ->
- Priv = ?config(priv_dir, Config),
- WD = filename:dirname(code:which(?MODULE)),
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-pa \"" ++ WD ++ "\""},
- {erl, [this]}]),
- CCTabCreated = fun(Tab) ->
- case ets:info(Tab, name) of
- code_cache -> true;
- _ -> false
- end
- end,
- Tabs0 = rpc:call(Node, ets, all, []),
- case rpc:call(Node, lists, any, [CCTabCreated,Tabs0]) of
- true ->
- ?t:stop_node(Node),
- ?t:fail("Code cache should not be active!");
- false ->
- ok
- end,
- ok = rpc:call(Node, code, rehash, []), % create cache
- Tabs1 = rpc:call(Node, ets, all, []),
- true = rpc:call(Node, lists, any, [CCTabCreated,Tabs1]), % cache table created
- ok = rpc:call(Node, code, rehash, []),
- OkDir = filename:join(Priv, ""),
- BadDir = filename:join(Priv, "guggemuffsussiputt"),
- CP = [OkDir | rpc:call(Node, code, get_path, [])],
- true = rpc:call(Node, code, set_path, [CP]),
- CP1 = [BadDir | CP],
- {error,_} = rpc:call(Node, code, set_path, [CP1]),
- true = rpc:call(Node, code, del_path, [OkDir]),
- true = rpc:call(Node, code, add_path, [OkDir]),
- true = rpc:call(Node, code, add_path, [OkDir]),
- {error,_} = rpc:call(Node, code, add_path, [BadDir]),
- ok = rpc:call(Node, code, rehash, []),
-
- ?t:stop_node(Node),
- ok.
-
-where_is_file_no_cache(suite) ->
- [];
-where_is_file_no_cache(doc) ->
- [];
-where_is_file_no_cache(Config) when is_list(Config) ->
+where_is_file(Config) when is_list(Config) ->
{T,KernelBeamFile} = timer:tc(code, where_is_file, ["kernel.beam"]),
io:format("Load time: ~w ms~n", [T]),
KernelEbinDir = filename:dirname(KernelBeamFile),
@@ -1046,35 +911,6 @@ where_is_file_no_cache(Config) when is_list(Config) ->
non_existing = code:where_is_file("kernel"), % no such file
ok.
-where_is_file_cached(suite) ->
- [];
-where_is_file_cached(doc) ->
- [];
-where_is_file_cached(Config) when is_list(Config) ->
- {ok,Node} =
- ?t:start_node(code_cache_node, peer, [{args,
- "-code_path_cache"},
- {erl, [this]}]),
- Tabs = rpc:call(Node, ets, all, []),
- io:format("Tabs: ~w~n", [Tabs]),
- CCTabCreated = fun(Tab) ->
- case rpc:call(Node, ets, info, [Tab,name]) of
- code_cache -> true;
- _ -> false
- end
- end,
- true = lists:any(CCTabCreated, Tabs),
- KernelBeamFile = rpc:call(Node, code, where_is_file, ["kernel.beam"]),
- {T,KernelBeamFile} = rpc:call(Node, timer, tc, [code,where_is_file,["kernel.beam"]]),
- io:format("Load time: ~w ms~n", [T]),
- KernelEbinDir = rpc:call(Node, filename, dirname, [KernelBeamFile]),
- AppFile = rpc:call(Node, filename, join, [KernelEbinDir,"kernel.app"]),
- AppFile = rpc:call(Node, code, where_is_file, ["kernel.app"]),
- non_existing = rpc:call(Node, code, where_is_file, ["kernel"]), % no such file
- ?t:stop_node(Node),
- ok.
-
-
purge_stacktrace(suite) ->
[];
purge_stacktrace(doc) ->
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 166eb3cef2..960c70f255 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -644,6 +644,8 @@ obsolete_1(httpd_conf, make_integer, 1) ->
obsolete_1(random, _, _) ->
{deprecated, "the 'random' module is deprecated; "
"use the 'rand' module instead"};
+obsolete_1(code, rehash, 0) ->
+ {deprecated, "deprecated because the code path cache feature has been removed"};
obsolete_1(_, _, _) ->
no.