The compiler freezing is mostly caused by a bug upstream,
but it may be speed up compilation to avoid purging as
we compile, as purging blocks the code server.
A potential downside is higher memory usage during
compilation.
Closes#13264.
We also extend Mix.Tasks.Compiler.Diagnostic
to include {line, column} as possible position.
We also explicitly document the behaviour of
line=0, which is equivalent to unknown line.
Elixir was already setting the line to zero in
multiple occasions prior to this patch, so this
patch makes it official and we stop returning `nil`
for said cases.
Before we would write:
lib/foo.ex compiled in 10ms (plus 100ms waiting)
However, because the file name is variable, it was
hard to see which file took the longest. Now we will
write:
10ms compiling + 100ms waiting for lib/foo.ex
By right aligning all times, we can easily look in
the first row and see which file took the longest.
We can also provide a summary option in the future,
if necessary.
The Elixir compiler spawns a separate process per file.
When a file has to wait on another module, Elixir tracks
in the compiler that the file is waiting.
However, every time a module is defined, the Elixir compiler
spawns a separate process to compile to .beam, and this
process may expand structs in the typespec. Since this
new process is no longer the original file process, Elixir
was not able to track its waiting time.
This PR address this issue by passing the original file_pid
to the .beam compiler process. Note though that, if we
change typespecs to be compiled in the original file process,
this change is no longer required, but at the moment there are
no plans to make such change.
Closes#11036.
Prior to this commit, compilation would copy the module map
(which is the map with the module definitions, attriubutes,
etc) multiple times. In particular, the module execution
process would pass it to the compiler. Then the module
execution process would send it to the parallel compiler
coordinator, which would pass it to the parallel checker
coordinator and then to each individual parallel checker.
That's four copies, which can be quite expensive since it
has the whole Elixir AST.
This commit makes it so it is copied only once. The map
is assembled inside the compiler process and then copied
to the checker process.
This has yielded good improvements in Elixir's test suite.
Before:
Finished in 27.3 seconds (14.4s on load, 7.0s async, 5.8s sync)
After:
Finished in 22.0 seconds (9.4s on load, 6.7s async, 5.8s sync)