Creating this issue with tag so we won't forget.
Some specific stuff that I believe should be in here:
rand(2,2) is one of the first thing you show someone in the REPL, nice to make that feel fast.More stuff?
By moving stuff to the stdlib we need to slightly tweak the way the precompilation file is postprocessed. For example, the REPL methods need to go to stdlib/REPL/precompile.jl since REPL is not defined in Base.
Messed around a bit with this so requesting some feedback here.
Currently, I tried the following (one file) approach. Enable the tracing, run julia and output to precompile.txt and then run the following script on it:
const HEADER = """
# This file is a part of Julia. License is MIT: https://julialang.org/license
# Steps to regenerate this file:
# 1. Remove all `precompile` calls
# 2. Rebuild system image
# 3. Enable TRACE_COMPILE in options.h and rebuild
# 4. Run `./julia 2> precompiles.txt` and do various things.
# 5. Run `./julia contrib/fixup_precompile.jl precompiles.txt
"""
function fixup_precompile(precompile_file)
precompile_file = joinpath(pwd(), ARGS[1])
precompile_statements = Set{String}()
for line in eachline(precompile_file)
# filter out closures, which might have different generated names in different environments)
contains(line, r"#[0-9]") && continue
# Other stuff than precompile statements might have been written to STDERR
startswith(line, "precompile(Tuple{") || continue
# Ok, add the line
push!(precompile_statements, line)
end
precompilefile_path = joinpath(Sys.BINDIR, "..", "..", "base", "precompile.jl")
open(precompilefile_path, "w") do f
println(f, HEADER)
println(f, "module __precompile_area__")
println(f, """
if !(pkgid.name in ("Main", "Core", "Base"))
@eval $(Symbol(mod)) = $mod
end""")
for statement in sort(collect(precompile_statements))
println(f, statement)
end
println(f, "end # module")
end
println("Wrote a new precompile file to $(abspath(precompilefile_path))")
end
@assert length(ARGS) == 1
fixup_precompile(ARGS[1])
This writes a precompile.jl file that looks like:
module __precompile_area__
for (pkgid, mod) in Base.loaded_modules
if !(pkgid.name in ("Main", "Core", "Base"))
@eval $(Symbol(mod)) = $mod
end
end
precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SlotNumber})
...
This just puts all the precompilation statements into one file. Since I "pseudo-import" all packages that are loaded, everything works nicely.
What is bad about this approach is that if you comment out a standard library that happens to have a method in the precompilation file, you will get an error there.
Possible solutions to this are:
Pkg and REPL would go into stdlib/Pkg/src/precompile.jl since Pkg requires REPL. This is perhaps nice since the precompilation statment will follow along the package if it is moved out of the repo.At one point, @vtjnash said it wouldn't be a problem to include precompile statements for other modules; related?
https://github.com/JuliaLang/julia/issues/23548
I'm not sure how that is related, could you elaborate? If you want to run a precompile statement all the types in the statement need to be defined. So we can't put a precompile statement that includes Pkg in the REPL precompile function because we have no reference to Pkg there. We could put it in Pkg though, or in the base sysimg like I explained above.
For triage it would be good to discuss:
I think for expediency in 0.7 and 1.0 we can do the simplest thing and put it in one file. We can do something fancier later.
Most helpful comment
By moving stuff to the stdlib we need to slightly tweak the way the precompilation file is postprocessed. For example, the REPL methods need to go to
stdlib/REPL/precompile.jlsinceREPLis not defined inBase.