From f48340039f5e0f4e571dd26371576e1facec8d5b Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 3 Jul 2015 15:18:28 +0000 Subject: Run agent as current process & hibernate This tries to reduce memory usage when running `rebar3 shell` by running the agent in the current process (and avoiding to copy state cross-boundaries), and using frequent hibernation after each run to force a full GC and compaction of the current process. --- src/rebar_agent.erl | 4 ++-- src/rebar_prv_shell.erl | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl index 24ac626..dc45dcf 100644 --- a/src/rebar_agent.erl +++ b/src/rebar_agent.erl @@ -26,11 +26,11 @@ init(State) -> handle_call({cmd, Command}, _From, State=#state{state=RState, cwd=Cwd}) -> MidState = maybe_show_warning(State), {Res, NewRState} = run(default, Command, RState, Cwd), - {reply, Res, MidState#state{state=NewRState}}; + {reply, Res, MidState#state{state=NewRState}, hibernate}; handle_call({cmd, Namespace, Command}, _From, State = #state{state=RState, cwd=Cwd}) -> MidState = maybe_show_warning(State), {Res, NewRState} = run(Namespace, Command, RState, Cwd), - {reply, Res, MidState#state{state=NewRState}}; + {reply, Res, MidState#state{state=NewRState}, hibernate}; handle_call(_Call, _From, State) -> {noreply, State}. diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index 84ad723..3c6369a 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -90,9 +90,10 @@ shell(State) -> %% their application masters never gets the new group leader (held in %% their internal state) maybe_boot_apps(State), - rebar_agent:start_link(State), - %% this call never returns (until user quits shell) - timer:sleep(infinity). + simulate_proc_lib(), + true = register(rebar_agent, self()), + {ok, GenState} = rebar_agent:init(State), + gen_server:enter_loop(rebar_agent, [], GenState, {local, rebar_agent}, hibernate). info() -> "Start a shell with project and deps preloaded similar to~n'erl -pa ebin -pa deps/*/ebin'.~n". @@ -145,6 +146,11 @@ maybe_boot_apps(State) -> boot_apps(Apps) end. +simulate_proc_lib() -> + FakeParent = spawn_link(fun() -> timer:sleep(infinity) end), + put('$ancestors', [FakeParent]), + put('$initial_call', {rebar_agent, init, 1}). + setup_name(State) -> {Opts, _} = rebar_state:command_parsed_args(State), case {proplists:get_value(name, Opts), proplists:get_value(sname, Opts)} of -- cgit v1.1