Open ronisbr opened 1 month ago
Assuming this is reproducible on master
, --trace-compile-timing
is useful to quickly identify major compilation offenders.
I cannot understand why I am seeing recompilation of functions like:
Seems to have gotten invalidated (yellow):
Assuming this is reproducible on master
Master seems a bit better:
0.097520 seconds (283.15 k allocations: 15.748 MiB, 99.31% compilation time: 58% of which was recompilation)
I do not know if there is a relationship, but I am seeing less specializations of external methods in cache using Julia 1.11:
Julia 1.11
julia> info_cachefile("PrettyTables")
Contents of /Users/ronan.arraes/.julia/compiled/v1.11/PrettyTables/kRdcL_Ky7mn.dylib:
modules: Any[PrettyTables]
145 external methods
3962 new specializations of external methods (Base 88.3%, Base.Broadcast 6.0%, Base.Sort 1.7%, ...)
436 external methods with new roots
11111 external targets
8519 edges
file size: 13715664 (13.080 MiB)
Segment sizes (bytes):
system: 5035516 ( 41.39%)
isbits: 6515800 ( 53.55%)
symbols: 29689 ( 0.24%)
tags: 83253 ( 0.68%)
relocations: 475609 ( 3.91%)
gvars: 10088 ( 0.08%)
fptrs: 17400 ( 0.14%)
Image targets:
apple-m2; flags=0; features_en=(aes, sha2, crc, lse, fullfp16, rdm, jsconv, complxnum, rcpc, ccpp, sha3, dotprod, fp16fml, dit, rcpc-immo, flagm, sb, ccdp, altnzcv, fptoint, i8mm, bf16, v8_1a, v8_2a, v8_3a, v8_4a, v8_5a)
Julia 1.10
julia> info_cachefile("PrettyTables")
Contents of /Users/ronan.arraes/.julia/compiled/v1.10/PrettyTables/kRdcL_YgcFH.dylib:
modules: Any[PrettyTables]
145 external methods
8279 new specializations of external methods (Base 77.5%, PrettyTables 11.3%, Base.Broadcast 5.5%, ...)
425 external methods with new roots
10904 external targets
8294 edges
file size: 10029936 (9.565 MiB)
Segment sizes (bytes):
system: 3889388 ( 44.37%)
isbits: 4355632 ( 49.69%)
symbols: 29427 ( 0.34%)
tags: 54666 ( 0.62%)
relocations: 409523 ( 4.67%)
gvars: 9632 ( 0.11%)
fptrs: 16720 ( 0.19%)
Image targets:
apple-m1; flags=0; features_en=(aes, sha2, crc, lse, fullfp16, rdm, jsconv, complxnum, rcpc, ccpp, sha3, dotprod, fp16fml, dit, rcpc-immo, flagm, sb, ccdp, altnzcv, fptoint, v8_1a, v8_2a, v8_3a, v8_4a, v8_5a)
@KristofferC I will check why the invalidations are happening. Is it expected due to some internal change in Julia 1.11?
Is it expected due to some internal change in Julia 1.11?
Potentially due to https://github.com/JuliaLang/StyledStrings.jl/issues/61 but I haven't verified.
There are a lot of new invalidations:
Julia 1.11
julia> trees = invalidation_trees(invalidations)
9-element Vector{SnoopCompile.MethodInvalidations}:
inserting match(re::Regex, s::LaTeXStrings.LaTeXString, idx::Integer, add_opts::UInt32) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:132 invalidated:
mt_backedges: 1: signature Tuple{typeof(match), Regex, AbstractString, Any, UInt32} triggered MethodInstance for iterate(::Base.RegexMatchIterator, ::Tuple{Int64, Bool}) (0 children)
2: signature Tuple{typeof(match), Regex, AbstractString, Any, UInt32} triggered MethodInstance for iterate(::Base.RegexMatchIterator, ::Tuple{Any, Bool}) (0 children)
3: signature Tuple{typeof(match), Regex, AbstractString, Any, UInt32} triggered MethodInstance for iterate(::Base.RegexMatchIterator, ::Tuple{Any, Any}) (0 children)
4: signature Tuple{typeof(match), Regex, AbstractString, Int64, UInt32} triggered MethodInstance for match(::Regex, ::Base.AnnotatedString, ::Int64, ::UInt32) (1 children)
5: signature Tuple{typeof(match), Regex, AbstractString, Integer, UInt32} triggered MethodInstance for match(::Regex, ::Base.AnnotatedString, ::Integer, ::UInt32) (4 children)
inserting convert(::Type{Vector{String}}, sa::LibGit2.StrArrayStruct) @ LibGit2 ~/.julia/juliaup/julia-1.11.0+0.aarch64.apple.darwin14/share/julia/stdlib/v1.11/LibGit2/src/strarray.jl:13 invalidated:
mt_backedges: 1: signature Tuple{typeof(convert), Type{Vector{String}}, Any} triggered MethodInstance for PrettyTables._text_fill_string_matrix!(::IOContext, ::Matrix{Vector{String}}, ::PrettyTables.ProcessedTable, ::Vector{Int64}, ::PrettyTables.Display, ::Ref{Any}, ::Vector{Int64}, ::Bool, ::Bool, ::Vector{Int64}, ::Bool, ::Bool, ::Bool, ::Bool, ::Vector{Int64}, ::Vector{Int64}, ::Val{:print}, ::Symbol) (9 children)
2: signature Tuple{typeof(convert), Type{Vector{String}}, Any} triggered MethodInstance for PrettyTables._preprocess_row_tables_jl(::Any, ::Nothing) (0 children)
3: signature Tuple{typeof(convert), Type{Vector{String}}, Any} triggered MethodInstance for PrettyTables._preprocess_column_tables_jl(::Any, ::Nothing) (0 children)
4: signature Tuple{typeof(convert), Type{Vector{String}}, Any} triggered MethodInstance for PrettyTables._text_fill_string_matrix!(::IOContext, ::Matrix{Vector{String}}, ::PrettyTables.ProcessedTable, ::Vector{Int64}, ::PrettyTables.Display, ::Ref{Any}, ::Vector{Int64}, ::Bool, ::Bool, ::Vector{Int64}, ::Bool, ::Bool, ::Bool, ::Bool, ::Vector{Int64}, ::Vector{Int64}, ::Val{:show}, ::Symbol) (0 children)
inserting firstindex(s::LaTeXStrings.LaTeXString) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:108 invalidated:
backedges: 1: superseding firstindex(s::AbstractString) @ Base strings/basic.jl:178 with MethodInstance for firstindex(::AbstractString) (17 children)
inserting print(io::IO, c::Base.AnnotatedChar) @ StyledStrings ~/.julia/juliaup/julia-1.11.0+0.aarch64.apple.darwin14/share/julia/stdlib/v1.11/StyledStrings/src/io.jl:281 invalidated:
backedges: 1: superseding print(io::IO, c::AbstractChar) @ Base char.jl:253 with MethodInstance for print(::IOBuffer, ::AbstractChar) (13 children)
2: superseding print(io::IO, c::AbstractChar) @ Base char.jl:253 with MethodInstance for print(::IOContext{IOBuffer}, ::AbstractChar) (5 children)
3: superseding print(io::IO, c::AbstractChar) @ Base char.jl:253 with MethodInstance for print(::IOContext{IOBuffer}, ::AbstractChar) (1 children)
4: superseding print(io::IO, c::AbstractChar) @ Base char.jl:253 with MethodInstance for print(::IOBuffer, ::AbstractChar) (1 children)
5: superseding print(io::IO, c::AbstractChar) @ Base char.jl:253 with MethodInstance for print(::IOContext{IOBuffer}, ::AbstractChar) (1 children)
6: superseding print(io::IO, c::AbstractChar) @ Base char.jl:253 with MethodInstance for print(::IOBuffer, ::AbstractChar) (3 children)
7: superseding print(io::IO, c::AbstractChar) @ Base char.jl:253 with MethodInstance for print(::IOBuffer, ::AbstractChar) (7 children)
inserting lastindex(s::LaTeXStrings.LaTeXString) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:109 invalidated:
backedges: 1: superseding lastindex(s::AbstractString) @ Base strings/basic.jl:179 with MethodInstance for lastindex(::AbstractString) (44 children)
inserting sizeof(s::LaTeXStrings.LaTeXString) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:127 invalidated:
backedges: 1: superseding sizeof(s::AbstractString) @ Base strings/basic.jl:177 with MethodInstance for sizeof(::AbstractString) (75 children)
inserting displaysize(t::REPL.Terminals.UnixTerminal) @ REPL.Terminals ~/.julia/juliaup/julia-1.11.0+0.aarch64.apple.darwin14/share/julia/stdlib/v1.11/REPL/src/Terminals.jl:153 invalidated:
backedges: 1: superseding displaysize(io::IO) @ Base stream.jl:568 with MethodInstance for displaysize(::IO) (77 children)
inserting displaysize(::REPL.Terminals.TextTerminal) @ REPL.Terminals ~/.julia/juliaup/julia-1.11.0+0.aarch64.apple.darwin14/share/julia/stdlib/v1.11/REPL/src/Terminals.jl:48 invalidated:
backedges: 1: superseding displaysize(io::IO) @ Base stream.jl:568 with MethodInstance for displaysize(::IO) (77 children)
inserting convert(::Type{String}, d::StringManipulation.Decoration) @ StringManipulation ~/.julia/packages/StringManipulation/bMZ2A/src/decorations.jl:365 invalidated:
mt_backedges: 1: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Base.UUID}, ::Any, ::Any) (0 children)
2: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{Bool, String}}, ::Any, ::Any) (0 children)
3: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{Nothing, String}}, ::Any, ::Any) (0 children)
4: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Nothing}, ::Nothing, ::Any) (0 children)
5: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{Nothing, Tuple{Base.PkgId, String}}}, ::Any, ::Any) (0 children)
6: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for push!(::Vector{String}, ::Any) (0 children)
7: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Pkg.Types.Compat}, ::Any, ::Any) (0 children)
8: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Vector{String}, ::Any, ::Int64) (7 children)
9: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for Base.RegexMatchIterator(::Regex, ::AbstractString, ::Bool) (11 children)
10: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for convert(::Type{Union{Nothing, String}}, ::Any) (19 children)
11: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for Base.Precompilation.ExplicitEnv(::String) (84 children)
Julia 1.10
julia> trees = invalidation_trees(invalidations)
5-element Vector{SnoopCompile.MethodInvalidations}:
inserting firstindex(s::LaTeXStrings.LaTeXString) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:108 invalidated:
backedges: 1: superseding firstindex(s::AbstractString) @ Base strings/basic.jl:180 with MethodInstance for firstindex(::AbstractString) (1 children)
inserting sizeof(s::LaTeXStrings.LaTeXString) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:127 invalidated:
backedges: 1: superseding sizeof(s::AbstractString) @ Base strings/basic.jl:179 with MethodInstance for sizeof(::AbstractString) (4 children)
inserting eachmatch(re::Regex, s::LaTeXStrings.LaTeXString; overlap) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:134 invalidated:
backedges: 1: superseding eachmatch(re::Regex, str::AbstractString; overlap) @ Base regex.jl:743 with MethodInstance for eachmatch(::Regex, ::AbstractString) (9 children)
inserting lastindex(s::LaTeXStrings.LaTeXString) @ LaTeXStrings ~/.julia/packages/LaTeXStrings/ZtSdh/src/LaTeXStrings.jl:109 invalidated:
backedges: 1: superseding lastindex(s::AbstractString) @ Base strings/basic.jl:181 with MethodInstance for lastindex(::AbstractString) (11 children)
inserting convert(::Type{String}, d::StringManipulation.Decoration) @ StringManipulation ~/.julia/packages/StringManipulation/bMZ2A/src/decorations.jl:365 invalidated:
mt_backedges: 1: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Base.UUID}, ::Any, ::Any) (0 children)
2: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{Bool, String}}, ::Any, ::Any) (0 children)
3: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{Nothing, String}}, ::Any, ::Any) (0 children)
4: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Nothing}, ::Nothing, ::Any) (0 children)
5: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{Nothing, Tuple{Base.PkgId, Union{Nothing, String}}}}, ::Any, ::Any) (0 children)
6: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{Base.SHA1, String}}, ::Any, ::Any) (0 children)
7: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Function}, ::Any, ::Any) (0 children)
8: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Vector{String}, ::Any, ::Int64) (0 children)
9: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Any}, ::Any, ::Any) (0 children)
10: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Union{String, Vector{String}}}, ::Any, ::Any) (0 children)
11: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Pkg.Types.Compat}, ::Any, ::Any) (0 children)
12: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Vector{String}}, ::Any, ::Any) (0 children)
13: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Base.UUID}, ::Base.UUID, ::Any) (0 children)
14: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{String, Vector{String}}, ::Vector{String}, ::Any) (0 children)
15: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for push!(::Vector{String}, ::Any) (0 children)
16: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Dict{Base.PkgId, String}, ::Any, ::Base.PkgId) (0 children)
17: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::IdDict{Any, String}, ::Any, ::Any) (1 children)
18: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for convert(::Type{Union{Nothing, String}}, ::Any) (2 children)
19: signature Tuple{typeof(convert), Union{Type{Base.UUID}, Type{VersionNumber}, Type{String}}, Any} triggered MethodInstance for (::Base.var"#cvt1#1"{Tuple{Base.UUID, String, String, VersionNumber}, Tuple{Base.UUID, Nothing, String, VersionNumber}})(::Int64) (3 children)
20: signature Tuple{typeof(convert), Union{Type{Base.UUID}, Type{VersionNumber}, Type{String}}, Any} triggered MethodInstance for (::Base.var"#cvt1#1"{Tuple{Base.UUID, String, String, VersionNumber}, Tuple{Base.UUID, Nothing, String, Pkg.Versions.VersionSpec}})(::Int64) (3 children)
21: signature Tuple{typeof(convert), Union{Type{Base.UUID}, Type{VersionNumber}, Type{String}}, Any} triggered MethodInstance for (::Base.var"#cvt1#1"{Tuple{Base.UUID, String, String, VersionNumber}, Tuple{Base.UUID, Nothing, String, Pkg.Types.UpgradeLevel}})(::Int64) (128 children)
@ronisbr, is it intended that this is not concretely typed?
There are quite a bit of type instabilities etc in PrettyTables, fixing those should make precompilation better. Just as an example in print_table
:
1000 1 ─ %1 = PrettyTables.get(io, :__PRETTY_TABLES_DATA__, PrettyTables.nothing)::Any │
1002 │ %2 = (%1 === PrettyTables.nothing)::Bool │
│ %3 = Core.Intrinsics.not_int(%2)::Bool │
└── goto #8 if not %3 │
1003 2 ─ %5 = PrettyTables.IOContext(io)::IOContext │
1008 │ %6 = Base.iterate(%1)::Any │
│ %7 = (%6 === nothing)::Bool │
│ %8 = Base.not_int(%7)::Bool │
└── goto #7 if not %8 │
3 ┄ %10 = φ (#2 => %6, #6 => %17)::Any │
│ %11 = Core.getfield(%10, 1)::Any │
│ %12 = Core.getfield(%10, 2)::Any │
1009 │ %13 = (%11 === data)::Bool │
└── goto #5 if not %13 │
1012 4 ─ invoke PrettyTables._pt_text_circular_reference(%5::IOContext) │
1019 └── return PrettyTables.nothing │
1021 5 ─ %17 = Base.iterate(%1, %12)::Any
Note that compilation time should be measured with @time @eval
.
Hi @KristofferC !
Yes, it is. When I tested those algorithms a long time ago, it was better to have those type instabilities and @nospecialize
because together with PrecompileTools.jl / SnoopCompile.jl I could drastically reduce the time to print the first table. The major problem was that if I remove the type instabilities, I start to see many slowdown at each input type and each output context (stdout
, a file, etc) due to the compilation.
However, since it was a long time ago, I will revisit given your suggestion. Thanks!
I was just checking. In Pkg we do a similar thing to avoid specializing on all IO types.
I found something very interesting! If I add REPL.jl as a dependency of PrettyTables.jl and add using REPL
without changing anything else, the overhead disappear completely:
julia> using PrettyTables
julia> A = ones(2, 2)
2×2 Matrix{Float64}:
1.0 1.0
1.0 1.0
julia> @time @eval pretty_table(A)
┌────────┬────────┐
│ Col. 1 │ Col. 2 │
├────────┼────────┤
│ 1.0 │ 1.0 │
│ 1.0 │ 1.0 │
└────────┴────────┘
0.070758 seconds (40.41 k allocations: 2.201 MiB, 50.82% gc time, 99.17% compilation time)
precompile(Tuple{typeof(Base.seek), Base.GenericIOBuffer{GenericMemory{:not_atomic, UInt8, Core.AddrSpace{Core}(0x00)}}, Int64})
precompile(Tuple{typeof(Base.something), REPL.LineEdit.Prompt, REPL.LineEdit.Prompt})
precompile(Tuple{typeof(Base.in), String, Array{String, 1}})
precompile(Tuple{typeof(REPL.LineEdit.history_prev_prefix), REPL.LineEdit.PrefixSearchState, REPL.REPLHistoryProvider, AbstractString})
precompile(Tuple{typeof(Base.ones), Int64, Int64})
precompile(Tuple{typeof(Base.show), Base.IOContext{Base.TTY}, Base.Multimedia.MIME{:var"text/plain"}, Array{Float64, 2}})
precompile(Tuple{typeof(Base.alignment), Base.IOContext{Base.TTY}, Float64})
precompile(Tuple{typeof(Base.show), Base.IOContext{Base.GenericIOBuffer{GenericMemory{:not_atomic, UInt8, Core.AddrSpace{Core}(0x00)}}}, String, Float64})
precompile(Tuple{typeof(Base.replace_in_print_matrix), Array{Float64, 2}, Int64, Int64, String})
precompile(Tuple{typeof(Base.repeat), Char, Int64})
precompile(Tuple{Type{Base.IOContext{IO_t} where IO_t<:IO}, Base.TTY, Pair{Symbol, Bool}})
precompile(Tuple{typeof(PrettyTables._preprocess_vec_or_mat), Array{Float64, 2}, Nothing})
precompile(Tuple{typeof(Base.get), Base.IOContext{Base.TTY}, Symbol, Nothing})
precompile(Tuple{typeof(PrettyTables._getdata), Array{Float64, 2}})
precompile(Tuple{Type{Base.IOContext{IO_t} where IO_t<:IO}, Base.IOContext{Base.TTY}, Pair{Symbol, Array{Any, 1}}})
precompile(Tuple{typeof(Core.kwcall), NamedTuple{(:alignment, :cell_alignment, :header_alignment, :header_cell_alignment, :max_num_of_columns, :max_num_of_rows, :show_header, :show_subheader), Tuple{Symbol, Nothing, Symbol, Nothing, Int64, Int64, Bool, Bool}}, Type{PrettyTables.ProcessedTable}, Array{Float64, 2}, Tuple{Array{String, 1}}})
precompile(Tuple{typeof(Base.setindex!), GenericMemory{:not_atomic, Int64, Core.AddrSpace{Core}(0x00)}, Int64, Int64})
precompile(Tuple{typeof(Base.escape_string), Base.GenericIOBuffer{GenericMemory{:not_atomic, UInt8, Core.AddrSpace{Core}(0x00)}}, String, String})
precompile(Tuple{typeof(PrettyTables._convert_axes), Array{Float64, 2}, Int64, Int64})
precompile(Tuple{Type{Base.IOContext{IO_t} where IO_t<:IO}, Base.IOContext{Base.TTY}, Pair{Symbol, Bool}, Pair{Symbol, Bool}})
precompile(Tuple{typeof(Core.kwcall), NamedTuple{(:context,), Tuple{Base.IOContext{Base.TTY}}}, typeof(Base.sprint), Function, Float64})
precompile(Tuple{typeof(PrettyTables._flush_display!), Base.IOContext{Base.TTY}, PrettyTables.Display, Bool, Bool, Int64})
precompile(Tuple{Type{NamedTuple{(:value, :time, :bytes, :gctime, :gcstats, :lock_conflicts, :compile_time, :recompile_time), T} where T<:Tuple}, Tuple{Nothing, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}})
precompile(Tuple{typeof(Base.getproperty), NamedTuple{(:value, :time, :bytes, :gctime, :gcstats, :lock_conflicts, :compile_time, :recompile_time), Tuple{Nothing, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}}, Symbol})
I have absolutely no idea why and I am also not sure if I can safely use this as a workaround.
Update: Adding only StyledStrings.jl as dependency and using StyledStrings
also helps to decrease the precompilation overhead (but not as much as doing the same with REPL.jl):
julia> using PrettyTables
julia> A = ones(2, 2)
2×2 Matrix{Float64}:
1.0 1.0
1.0 1.0
julia> @time @eval pretty_table(A)
┌────────┬────────┐
│ Col. 1 │ Col. 2 │
├────────┼────────┤
│ 1.0 │ 1.0 │
│ 1.0 │ 1.0 │
└────────┴────────┘
0.095050 seconds (260.66 k allocations: 14.747 MiB, 39.18% gc time, 99.41% compilation time: 70% of which was recompilation)
I have absolutely no idea why and I am also not sure if I can safely use this as a workaround.
Probably because your methods are then defined after these https://github.com/JuliaLang/StyledStrings.jl/issues/61 so they don't get invalidated. In 1.10 this was not an issue because REPL and everything else was in the sysimage so they were effectively a dependency to all other packages.
I have absolutely no idea why and I am also not sure if I can safely use this as a workaround.
Probably because your methods are then defined after these JuliaLang/StyledStrings.jl#61 so they don't get invalidated. In 1.10 this was not an issue because REPL and everything else was in the sysimage so they were effectively a dependency to all other packages.
Makes sense! So, I think I can safely add REPL as dependency until it gets fixed right?
Your package will be slower to load though because it has to load REPL unconditionally.
@KristofferC I am getting some very strange results:
Before Adding REPL.jl as Dependency
julia> @time_imports using PrettyTables
0.6 ms Reexport
0.3 ms DataValueInterfaces
0.7 ms DataAPI
0.4 ms IteratorInterfaceExtensions
0.3 ms TableTraits
2.3 ms OrderedCollections
5.2 ms Tables
0.5 ms Printf
14.7 ms Dates
0.4 ms TOML
5.5 ms Preferences
0.3 ms PrecompileTools
3.6 ms StringManipulation
5.8 ms Crayons
0.5 ms LaTeXStrings
39.9 ms PrettyTables
After Adding REPL.jl as Dependency
julia> @time_imports using PrettyTables
0.7 ms Reexport
0.4 ms DataValueInterfaces
0.7 ms DataAPI
0.4 ms IteratorInterfaceExtensions
0.4 ms TableTraits
2.1 ms OrderedCollections
4.7 ms Tables
0.5 ms Printf
14.3 ms Dates
0.4 ms TOML
5.2 ms Preferences
0.3 ms PrecompileTools
3.4 ms StringManipulation
5.7 ms Crayons
0.4 ms LaTeXStrings
39.6 ms PrettyTables
Do you think it might be something related to my setup? I tested in 3 different computers with the same result.
You are in the REPL so the REPL is already loaded. Run it from a script for example.
Ah! Sorry :) My bad, I thought REPL.jl now contains only some extra functionalities and not the REPL itself.
While investigating this morning, I noticed that the "recompilation" metric is lying to us: https://github.com/JuliaLang/julia/issues/56155
Many of the functions "re-compiled" here are actually things that were inferred when we built the sysimage. They just never got any code. For example, Base.Filesystems.contractuser(::String)
is one of the things that is compiled on 1.10, and on 1.11+ it is inferred only. The difference is because contractuser(::String)
became eligible for inlining..
On 1.10, inlining_cost
for contractuser(::String)
is UINT16_MAX
which causes it to be triggered for code generation during sysimage generation. On 1.11+ the cost is 81:
using Base.Filesystem: contractuser
mi = methods(contractuser, (String,))[1].specializations::Base.MethodInstance
println(ccall(:jl_ir_inlining_cost, UInt16, (Any,), mi.cache.inferred))
$ julia +1.11 inlining_cost.jl
81
$ julia +1.10 inlining_cost.jl
65535
If the compiler sees that a method is inline-able and has not been codegen'd yet, it will decide that it is not worth compiling, under the assumption that it's most likely to end up inlined everywhere (and so generating a separate function for it would be useless).
Maybe we need to revisit that compilation decision?
Hi!
I am seeing a huge precompilation overhead using Julia 1.11:
Julia 1.10
Julia 1.11
This issue leads to a very large time to print the first table in PrettyTables.jl. Unfortunately, I could not obtain a minimum working example.
Using
--track-compilation
, as suggested by @giordano, leads to:Julia 1.10
Julia 1.11
Is this expected? Is there anything I can do to improve it?
Although I am not 100% sure, I remember testing it in a very earlier version of 1.11 and found not big discrepancy.
EDIT: I cannot understand why I am seeing recompilation of functions like:
since I am using PrecompileTools.jl and it should be already precompiled.