SymbolicML / DynamicQuantities.jl

Efficient and type-stable physical quantities in Julia
https://symbolicml.org/DynamicQuantities.jl/dev/
Apache License 2.0
121 stars 15 forks source link

Further improvements to startup time #67

Closed MilesCranmer closed 8 months ago

MilesCranmer commented 9 months ago

cc @devmotion

The current startup time is about 40 ms on v1.10. This is pretty good! For comparison, Unitful.jl is 150 ms.

But I think we can do even better. Following along with https://sciml.ai/news/2022/09/21/compile_time/, it seems like a good way for improving startup time is looking at invalidations. The current list of invalidations, on my startup file, is:

julia> using SnoopCompileCore;

julia> invalidations = @snoopr begin
           using DynamicQuantities
       end;

julia> using SnoopCompile;

julia> trees = invalidation_trees(invalidations)
12-element Vector{SnoopCompile.MethodInvalidations}:
 inserting deleteat!(t::BenchmarkTools.Trial, i) @ BenchmarkTools ~/.julia/packages/BenchmarkTools/0owsb/src/trials.jl:33 invalidated:
   mt_backedges: 1: signature Tuple{typeof(deleteat!), Any, Int64} triggered MethodInstance for DynamicQuantities.UnitsParse._generate_units_import() (0 children)

 inserting deleteat!(listStore::Gtk.GtkListStoreLeaf, index::Int64) @ Gtk ~/.julia/packages/Gtk/oo3cW/src/lists.jl:182 invalidated:
   mt_backedges: 1: signature Tuple{typeof(deleteat!), Any, Int64} triggered MethodInstance for DynamicQuantities.UnitsParse._generate_units_import() (0 children)

 inserting deleteat!(w::Gtk.GtkContainer, i::Integer) @ Gtk ~/.julia/packages/Gtk/oo3cW/src/container.jl:10 invalidated:
   mt_backedges: 1: signature Tuple{typeof(deleteat!), Any, Int64} triggered MethodInstance for DynamicQuantities.UnitsParse._generate_units_import() (0 children)

 inserting promote(x::Integer, y::F) where F<:FixedRational @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/fixed_rational.jl:86 invalidated:
   backedges: 1: superseding promote(x, y) @ Base promotion.jl:391 with MethodInstance for promote(::Int64, ::Real) (1 children)

 inserting isless(l::AbstractQuantity, r) @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/utils.jl:78 invalidated:
   mt_backedges: 1: signature Tuple{typeof(isless), Any, Char} triggered MethodInstance for <(::Any, ::Char) (1 children)

 inserting isless(l, r::AbstractQuantity) @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/utils.jl:82 invalidated:
   mt_backedges: 1: signature Tuple{typeof(isless), Char, Any} triggered MethodInstance for <(::Char, ::Any) (1 children)

 inserting convert(::Type{F}, x::Integer) where F<:FixedRational @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/fixed_rational.jl:58 invalidated:
   backedges: 1: superseding convert(::Type{T}, x::Number) where T<:Number @ Base number.jl:7 with MethodInstance for convert(::Type{T} where T<:Real, ::Int64) (2 children)

 inserting convert(::Type{I}, x::F) where {I<:Integer, F<:FixedRational} @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/fixed_rational.jl:63 invalidated:
   backedges: 1: superseding convert(::Type{T}, x::Number) where T<:Number @ Base number.jl:7 with MethodInstance for convert(::Type{Int64}, ::Real) (3 children)

 inserting promote(x::F, y::Integer) where F<:FixedRational @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/fixed_rational.jl:87 invalidated:
   backedges: 1: superseding promote(x, y) @ Base promotion.jl:391 with MethodInstance for promote(::Real, ::Int64) (1 children)
              2: superseding promote(x, y) @ Base promotion.jl:391 with MethodInstance for promote(::Any, ::Any) (14 children)

 inserting +(l, r::AbstractQuantity) @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/math.jl:32 invalidated:
   mt_backedges:  1: signature Tuple{typeof(+), Ptr{UInt8}, Any} triggered MethodInstance for Base.GMP.var"#string#4"(::Int64, ::Integer, ::typeof(string), ::BigInt) (0 children)
                  2: signature Tuple{typeof(+), Ptr{Nothing}, Any} triggered MethodInstance for Gtk.GLib.GClosureMarshal(::Ptr{Nothing}, ::Ptr{Gtk.GLib.GValue}, ::UInt32, ::Ptr{Gtk.GLib.GValue}, ::Ptr{Nothing}, ::Ptr{Nothing}) (0 children)
               ...
                 73: signature Tuple{typeof(+), Ptr{Nothing}, Any} triggered MethodInstance for Gtk.GLib._signal_connect(::Function, ::Gtk.GtkEntryLeaf, ::String, ::Bool, ::Bool, ::Nothing, ::Nothing) (31 children)

 inserting ==(l, r::AbstractQuantity) @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/utils.jl:72 invalidated:
   backedges:  1: superseding ==(x, y) @ Base Base.jl:159 with MethodInstance for ==(::Core.MethodInstance, ::Any) (6 children)
               2: superseding ==(x, y) @ Base Base.jl:159 with MethodInstance for ==(::Gtk.GLib.GObject, ::Any) (6 children)
               ...
              40: superseding ==(x, y) @ Base Base.jl:159 with MethodInstance for ==(::Core.TypeName, ::Any) (120 children)

 inserting ==(l::AbstractQuantity, r) @ DynamicQuantities ~/Documents/DynamicQuantities.jl/src/utils.jl:73 invalidated:
   backedges: 1: superseding ==(x, y) @ Base Base.jl:159 with MethodInstance for ==(::Any, ::Core.Compiler.InferenceResult) (5 children)
              2: superseding ==(x, y) @ Base Base.jl:159 with MethodInstance for ==(::Any, ::Cthulhu.DInfo.DebugInfo) (6 children)
              ...
              7: superseding ==(x, y) @ Base Base.jl:159 with MethodInstance for ==(::Any, ::Gtk.GLib.GObject) (446 children)

I think many of these can be deleted, getting rid of the invalidation. Although it might make sense to wait for https://github.com/SymbolicML/DynamicQuantities.jl/pull/49 first, since that will change how we go about this. (e.g., dispatching on Number for the == methods).

MilesCranmer commented 8 months ago

To be fixed by #71