You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ko...@apache.org on 2021/01/20 23:05:02 UTC
[couchdb] 01/02: Simplify and speedup dev node startup
This is an automated email from the ASF dual-hosted git repository.
kocolosk pushed a commit to branch 3.x-devnode-boot-script
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 9fb0624168d6bb0643433de1a23d42851c841ec8
Author: Adam Kocoloski <ko...@apache.org>
AuthorDate: Wed Jan 20 17:54:24 2021 -0500
Simplify and speedup dev node startup
This patch introduces an escript that generates an Erlang .boot script
to start CouchDB using the in-place .beam files produced by the compile
phase of the build. This allows us to radically simplify the boot
process as Erlang computes the optimal order for loading the necessary
modules.
In addition to the simplification this approach offers a significant
speedup when working inside a container environment. In my test with
the stock .devcontainer it reduces startup time from about 75 seconds
down to under 5 seconds.
---
.gitignore | 1 +
Makefile | 2 +-
dev/boot_node.erl | 105 ---------------------------------------------------
dev/make_boot_script | 9 +++++
dev/run | 13 +++++--
5 files changed, 21 insertions(+), 109 deletions(-)
diff --git a/.gitignore b/.gitignore
index c594b10..f84b9f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@ config.erl
*.tar.gz
*.tar.bz2
dev/boot_node.beam
+dev/devnode.*
dev/lib/
dev/logs/
ebin/
diff --git a/Makefile b/Makefile
index 184f9b0..6815f38 100644
--- a/Makefile
+++ b/Makefile
@@ -410,7 +410,7 @@ clean:
@rm -rf src/mango/.venv
@rm -f src/couch/priv/couchspawnkillable
@rm -f src/couch/priv/couch_js/config.h
- @rm -f dev/boot_node.beam dev/pbkdf2.pyc log/crash.log
+ @rm -f dev/boot_node.beam dev/devnode.* dev/pbkdf2.pyc log/crash.log
.PHONY: distclean
diff --git a/dev/boot_node.erl b/dev/boot_node.erl
index 922a5cc..e4ed513 100644
--- a/dev/boot_node.erl
+++ b/dev/boot_node.erl
@@ -16,13 +16,6 @@
start() ->
- monitor_parent(),
- Apps = load_apps(),
- Deps = load_deps(Apps),
- start_all_apps(Deps).
-
-
-monitor_parent() ->
{ok, [[PPid]]} = init:get_argument(parent_pid),
spawn(fun() -> monitor_parent(PPid) end).
@@ -48,101 +41,3 @@ monitor_parent(PPid) ->
init:stop()
end
end.
-
-
-load_apps() ->
- {ok, [[Config]]} = init:get_argument(reltool_config),
- {ok, Terms} = file:consult(Config),
- load_apps(Terms).
-
-
-load_apps([]) ->
- erlang:error(failed_to_load_apps);
-load_apps([{sys, Terms} | _]) ->
- load_apps(Terms);
-load_apps([{rel, "couchdb", _Vsn, Apps} | _]) ->
- Apps;
-load_apps([_ | Rest]) ->
- load_apps(Rest).
-
-
-load_deps(Apps) ->
- load_deps(Apps, dict:new()).
-
-
-load_deps([], Deps) ->
- Deps;
-load_deps([App | Rest], Deps) ->
- load_app(App),
- case application:get_key(App, applications) of
- {ok, AppDeps0} ->
- NewDeps = dict:store(App, AppDeps0, Deps),
- Filter = fun(A) -> not dict:is_key(A, Deps) end,
- AppDeps = lists:filter(Filter, AppDeps0),
- load_deps(AppDeps ++ Rest, NewDeps);
- _ ->
- NewDeps = dict:store(App, [], Deps),
- load_deps(Rest, NewDeps)
- end.
-
-
-load_app(App) ->
- case application:load(App) of
- ok ->
- case application:get_key(App, modules) of
- {ok, Modules} ->
- lists:foreach(fun(Mod) ->
- case load_app_module(Mod) of
- ok -> ok;
- E -> io:format("~p = load_app_module(~p)~n", [E, Mod])
- end
- end, Modules);
- undefined ->
- ok
- end;
- {error, {already_loaded, App}} ->
- ok;
- Error ->
- Error
- end.
-
-
-load_app_module(Mod) ->
- case code:is_loaded(Mod) of
- {file, _} ->
- ok;
- _ ->
- case code:load_file(Mod) of
- {module, Mod} ->
- ok;
- Error ->
- Error
- end
- end.
-
-
-start_all_apps(Deps) ->
- lists:foldl(fun(App, Started) ->
- start_app(App, Deps, Started)
- end, [], dict:fetch_keys(Deps)).
-
-
-start_app(App, Deps, Started) ->
- case lists:member(App, Started) of
- true ->
- Started;
- false ->
- AppDeps = dict:fetch(App, Deps),
- NowStarted = lists:foldl(fun(Dep, Acc) ->
- start_app(Dep, Deps, Acc)
- end, Started, AppDeps),
- case application:start(App) of
- ok ->
- [App | NowStarted];
- {error, {already_started,App}} ->
- % Kernel causes this
- [App | NowStarted];
- Else ->
- erlang:error(Else)
- end
- end.
diff --git a/dev/make_boot_script b/dev/make_boot_script
new file mode 100755
index 0000000..549dd9a
--- /dev/null
+++ b/dev/make_boot_script
@@ -0,0 +1,9 @@
+#!/usr/bin/env escript
+
+main(_) ->
+ {ok, Server} = reltool:start_server([
+ {config, "../rel/reltool.config"}
+ ]),
+ {ok, Release} = reltool:get_rel(Server, "couchdb"),
+ ok = file:write_file("devnode.rel", io_lib:format("~p.~n", [Release])),
+ ok = systools:make_script("devnode", [local]).
diff --git a/dev/run b/dev/run
index 6d8bc52..210895a 100755
--- a/dev/run
+++ b/dev/run
@@ -101,6 +101,7 @@ def setup():
setup_logging(ctx)
setup_dirs(ctx)
check_beams(ctx)
+ check_boot_script(ctx)
setup_configs(ctx)
return ctx
@@ -267,6 +268,12 @@ def check_beams(ctx):
for fname in glob.glob(os.path.join(ctx["devdir"], "*.erl")):
sp.check_call(["erlc", "-o", ctx["devdir"] + os.sep, fname])
+@log("Ensure Erlang boot script exists")
+def check_boot_script(ctx):
+ if not os.path.exists(os.path.join(ctx["devdir"], "devnode.boot")):
+ env = os.environ.copy()
+ env["ERL_LIBS"] = os.path.join(ctx["rootdir"], "src")
+ sp.check_call(["escript", "make_boot_script"], env=env, cwd=ctx["devdir"])
@log("Prepare configuration files")
def setup_configs(ctx):
@@ -592,10 +599,9 @@ def set_boot_env(ctx):
@log("Start node {node}")
def boot_node(ctx, node):
- erl_libs = os.path.join(ctx["rootdir"], "src")
set_boot_env(ctx)
env = os.environ.copy()
- env["ERL_LIBS"] = os.pathsep.join([erl_libs])
+ env["ERL_LIBS"] = os.path.join(ctx["rootdir"], "src")
node_etcdir = os.path.join(ctx["devdir"], "lib", node, "etc")
reldir = os.path.join(ctx["rootdir"], "rel")
@@ -614,10 +620,11 @@ def boot_node(ctx, node):
os.path.join(reldir, "reltool.config"),
"-parent_pid",
str(os.getpid()),
+ "-boot",
+ os.path.join(ctx["devdir"], "devnode"),
"-pa",
ctx["devdir"],
]
- cmd += [p[:-1] for p in glob.glob(erl_libs + "/*/")]
cmd += ["-s", "boot_node"]
if ctx["reset_logs"]:
mode = "wb"