Skip to content

Commit e024a12

Browse files
committed
Load apps concurrently
1 parent 42807d2 commit e024a12

File tree

1 file changed

+37
-19
lines changed

1 file changed

+37
-19
lines changed

lib/mix/lib/mix/tasks/compile.all.ex

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,32 +95,50 @@ defmodule Mix.Tasks.Compile.All do
9595

9696
defp load_apps(config, validate_compile_env?) do
9797
{runtime, optional} = Mix.Tasks.Compile.App.project_apps(config)
98+
parent = self()
99+
opts = [ordered: false, timeout: :infinity]
98100

99-
%{}
100-
|> load_apps(runtime, validate_compile_env?)
101-
|> load_apps(optional, validate_compile_env?)
101+
stream_apps(runtime ++ optional)
102+
|> Task.async_stream(&load_app(&1, parent, validate_compile_env?), opts)
103+
|> Stream.run()
104+
end
105+
106+
defp load_app(app, parent, validate_compile_env?) do
107+
case load_app(app, validate_compile_env?) do
108+
:ok ->
109+
send(parent, {:done, app, Application.spec(app, :applications) ++ Application.spec(app, :included_applications)})
110+
111+
:error ->
112+
send(parent, {:done, app, []})
113+
end
102114

103115
:ok
104116
end
105117

106-
defp load_apps(seen, apps, validate_compile_env?) do
107-
Enum.reduce(apps, seen, fn app, seen ->
108-
if Map.has_key?(seen, app) do
109-
seen
110-
else
111-
seen = Map.put(seen, app, true)
118+
defp stream_apps(initial) do
119+
Stream.unfold({initial, %{}, %{}}, &stream_app/1)
120+
end
112121

113-
case load_app(app, validate_compile_env?) do
114-
:ok ->
115-
seen
116-
|> load_apps(Application.spec(app, :applications), validate_compile_env?)
117-
|> load_apps(Application.spec(app, :included_applications), validate_compile_env?)
122+
# We already processed this app, skip it.
123+
defp stream_app({[app | apps], seen, done}) when is_map_key(seen, app) do
124+
stream_app({apps, seen, done})
125+
end
118126

119-
:error ->
120-
seen
121-
end
122-
end
123-
end)
127+
# We haven't processed this app, emit it.
128+
defp stream_app({[app | apps], seen, done}) do
129+
{app, {apps, Map.put(seen, app, true), done}}
130+
end
131+
132+
# We have processed all apps and all seen have been done.
133+
defp stream_app({[], seen, done}) when map_size(seen) == map_size(done) do
134+
nil
135+
end
136+
137+
# We have processed all apps but there is work being done.
138+
defp stream_app({[], seen, done}) do
139+
receive do
140+
{:done, app, children} -> stream_app({children, seen, Map.put(done, app, true)})
141+
end
124142
end
125143

126144
defp load_app(app, validate_compile_env?) do

0 commit comments

Comments
 (0)