Skip to content

Commit a0c0cb6

Browse files
Gazlerjosevalim
authored andcommitted
Use heuristic for compiler errors (#4778)
Previously when all files being compiled get stuck waiting on something else, we would release those files in random order. This commit changes this to release files in groups based on the module they are waiting on. We pick the module being depended on with less edges, as it is mostly likely being the cause of conflict. This may not always be true though: for example, if there is a macro injecting code into multiple modules and such code becomes faulty, now multiple modules are waiting on this same module. However, we have to pick one or the other, and we decided to pick the one with fewer dependencies.
1 parent 28790df commit a0c0cb6

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

lib/elixir/lib/kernel/parallel_compiler.ex

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,15 @@ defmodule Kernel.ParallelCompiler do
137137
# Queued x, waiting for x: POSSIBLE ERROR! Release processes so we get the failures
138138
defp spawn_compilers(%{entries: [], waiting: waiting, queued: queued} = state) when length(waiting) == length(queued) do
139139
entries = for {pid, _, _, _} <- queued,
140-
not waiting_on_is_being_defined?(waiting, pid),
141-
do: {pid, :not_found}
140+
on = waiting_on_without_definition(waiting, pid),
141+
do: {on, {pid, :not_found}}
142+
143+
entries =
144+
entries
145+
|> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
146+
|> Enum.sort_by(&length(elem(&1, 1)))
147+
|> Enum.at(0, {__MODULE__, []})
148+
|> elem(1)
142149

143150
case entries do
144151
[] -> handle_deadlock(waiting, queued)
@@ -151,9 +158,13 @@ defmodule Kernel.ParallelCompiler do
151158
wait_for_messages(state)
152159
end
153160

154-
defp waiting_on_is_being_defined?(waiting, pid) do
161+
defp waiting_on_without_definition(waiting, pid) do
155162
{_kind, ^pid, _, on, _defining} = List.keyfind(waiting, pid, 1)
156-
Enum.any?(waiting, fn {_, _, _, _, defining} -> on in defining end)
163+
if Enum.any?(waiting, fn {_, _, _, _, defining} -> on in defining end) do
164+
nil
165+
else
166+
on
167+
end
157168
end
158169

159170
# Wait for messages from child processes

0 commit comments

Comments
 (0)