瀏覽代碼

Enable parallel build

Support for parallel compilation of *.erl file was dropped before 3.0 release.
However, our tests for a project containing ~500 source files show substantial gain, lowering compilation time from 58 seconds to 18 on a MacBook Pro 15" (4 cores, 8 threads), and to just 10 seconds on Xeon-D machine.
pull/2039/head
Maxim Fedorov 6 年之前
父節點
當前提交
ae0af35e8c
共有 1 個檔案被更改,包括 55 行新增1 行删除
  1. +55
    -1
      src/rebar_compiler.erl

+ 55
- 1
src/rebar_compiler.erl 查看文件

@ -77,7 +77,7 @@ run(CompilerMod, AppInfo, Label) ->
true = digraph:delete(G),
compile_each(FirstFiles, FirstFileOpts, BaseOpts, Mappings, CompilerMod),
compile_each(RestFiles, Opts, BaseOpts, Mappings, CompilerMod).
compile_parallel(RestFiles, Opts, BaseOpts, Mappings, CompilerMod).
compile_each([], _Opts, _Config, _Outs, _CompilerMod) ->
ok;
@ -99,6 +99,60 @@ compile_each([Source | Rest], Opts, Config, Outs, CompilerMod) ->
end,
compile_each(Rest, Opts, Config, Outs, CompilerMod).
compile_worker(QueuePid, Opts, Config, Outs, CompilerMod) ->
QueuePid ! self(),
receive
{compile, Source} ->
Result = CompilerMod:compile(Source, Outs, Config, Opts),
QueuePid ! {Result, Source},
compile_worker(QueuePid, Opts, Config, Outs, CompilerMod);
empty ->
ok
end.
compile_parallel([], _Opts, _BaseOpts, _Mappings, _CompilerMod) ->
ok;
compile_parallel(Targets, Opts, BaseOpts, Mappings, CompilerMod) ->
Self = self(),
F = fun() -> compile_worker(Self, Opts, BaseOpts, Mappings, CompilerMod) end,
Jobs = min(length(Targets), erlang:system_info(schedulers)),
?DEBUG("Starting ~B compile worker(s)", [Jobs]),
Pids = [spawn_monitor(F) || _I <- lists:seq(1, Jobs)],
compile_queue(Targets, Pids, Opts, BaseOpts, Mappings, CompilerMod).
compile_queue([], [], _Opts, _Config, _Outs, _CompilerMod) ->
ok;
compile_queue(Targets, Pids, Opts, Config, Outs, CompilerMod) ->
receive
Worker when is_pid(Worker), Targets =:= [] ->
Worker ! empty,
compile_queue(Targets, Pids, Opts, Config, Outs, CompilerMod);
Worker when is_pid(Worker) ->
Worker ! {compile, hd(Targets)},
compile_queue(tl(Targets), Pids, Opts, Config, Outs, CompilerMod);
{ok, Source} ->
?DEBUG("~sCompiled ~s", [rebar_utils:indent(1), filename:basename(Source)]),
compile_queue(Targets, Pids, Opts, Config, Outs, CompilerMod);
{{ok, Warnings}, Source} ->
report(Warnings),
?DEBUG("~sCompiled ~s", [rebar_utils:indent(1), filename:basename(Source)]),
compile_queue(Targets, Pids, Opts, Config, Outs, CompilerMod);
{skipped, Source} ->
?DEBUG("~sSkipped ~s", [rebar_utils:indent(1), filename:basename(Source)]),
compile_queue(Targets, Pids, Opts, Config, Outs, CompilerMod);
{Error, Source} ->
NewSource = format_error_source(Source, Config),
?ERROR("Compiling ~ts failed", [NewSource]),
maybe_report(Error),
?FAIL;
{'DOWN', Mref, _, Pid, normal} ->
Pids2 = lists:delete({Pid, Mref}, Pids),
compile_queue(Targets, Pids2, Opts, Config, Outs, CompilerMod);
{'DOWN', _Mref, _, _Pid, Info} ->
?ERROR("Compilation failed: ~p", [Info]),
?FAIL
end.
%% @doc remove compiled artifacts from an AppDir.
-spec clean([module()], rebar_app_info:t()) -> 'ok'.
clean(Compilers, AppInfo) ->

Loading…
取消
儲存