Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce invalidations #84

Open
sethaxen opened this issue Feb 28, 2023 · 2 comments
Open

Reduce invalidations #84

sethaxen opened this issue Feb 28, 2023 · 2 comments

Comments

@sethaxen
Copy link

Loading DataValues causes a lot of invalidations, which in turn require a lot of already loaded package code to be recompiled (see at the bottom of this post):

It would be nice to at least fix these methods, which together invalidate about 9,000 methods:

==(a::DataValue{T1}, b::T2) where {T1,T2} = isna(a) ? false : unsafe_get(a) == b

Base.convert(::Type{Any}, ::DataValue{Union{}}) = NA
(proposed to be removed in #51)
==(a::T1, b::DataValue{T2}) where {T1,T2} = isna(b) ? false : a == unsafe_get(b)

Here are the invalidations on v1.8:

julia> using SnoopCompileCore

julia> invalidations = @snoopr using DataValues;

julia> using SnoopCompile

julia> trees = invalidation_trees(invalidations)
13-element Vector{SnoopCompile.MethodInvalidations}:
 inserting convert(::Type{Array{S, N}}, X::DataValueArray{T, N}) where {S, T, N} in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/array/primitives.jl:271 invalidated:
   mt_backedges: 1: signature Tuple{typeof(convert), Type{Vector{Any}}, Any} triggered MethodInstance for setindex!(::Vector{Vector{Any}}, ::Any, ::Int64) (0 children)

 inserting |(x::DataValue{Bool}, y::Bool) in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/scalar/core.jl:272 invalidated:
   mt_backedges: 1: signature Tuple{typeof(|), Any, Bool} triggered MethodInstance for Base._base(::Int64, ::Integer, ::Int64, ::Bool) (0 children)

 inserting ^(a::T1, b::DataValue{T2}) where {T1, T2} in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/scalar/operations.jl:75 invalidated:
   mt_backedges: 1: signature Tuple{typeof(^), String, Any} triggered MethodInstance for OhMyREPL.untokenize_with_ANSI(::IOContext{IOBuffer}, ::Vector{Crayons.Crayon}, ::Vector{Tokenize.Tokens.Token}, ::Any) (0 children)

 inserting &(x::Bool, y::DataValue{Bool}) in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/scalar/core.jl:254 invalidated:
   mt_backedges: 1: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for div(::Unsigned, ::Int64, ::RoundingMode{:Down}) (0 children)
                 2: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for div(::Unsigned, ::Int64, ::RoundingMode{:Up}) (0 children)
                 3: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for Base.var"#string#427"(::Int64, ::Int64, ::typeof(string), ::Unsigned) (0 children)

 inserting mapreduce(f, op::Function, X::T; skipna) where {N, S<:DataValue, T<:AbstractArray{S, N}} in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/array/reduce.jl:109 invalidated:
   backedges: 1: superseding mapreduce(f, op, A::Union{Base.AbstractBroadcasted, AbstractArray}; dims, init) in Base at reducedim.jl:357 with MethodInstance for mapreduce(::Base.ExtremaMap{typeof(identity)}, ::typeof(Base._extrema_rf), ::Vector) (8 children)

 inserting similar(x::AbstractArray, ::Type{DataValue{T}}, dims::Tuple{Vararg{Int64, N}} where N) where T in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/array/primitives.jl:12 invalidated:
   backedges: 1: superseding similar(a::AbstractArray, ::Type{T}, dims::Tuple{Vararg{Int64, N}}) where {T, N} in Base at abstractarray.jl:806 with MethodInstance for similar(::UnitRange{Int64}, ::Type, ::Tuple{Int64}) (3 children)
              2: superseding similar(a::AbstractArray, ::Type{T}, dims::Tuple{Vararg{Int64, N}}) where {T, N} in Base at abstractarray.jl:806 with MethodInstance for similar(::UnitRange{Int64}, ::DataType, ::Tuple{Int64}) (3 children)
              3: superseding similar(a::AbstractArray, ::Type{T}, dims::Tuple{Vararg{Int64, N}}) where {T, N} in Base at abstractarray.jl:806 with MethodInstance for similar(::UnitRange{Int64}, ::Type, ::Tuple{Int64}) (6 children)
   1 mt_cache

 inserting convert(::Type{Array}, X::DataValueArray{T, N}) where {T, N} in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/array/primitives.jl:291 invalidated:
   backedges: 1: superseding convert(::Type{T}, a::AbstractArray) where T<:Array in Base at array.jl:617 with MethodInstance for convert(::Type, ::AbstractArray) (15 children)
   29 mt_cache

 inserting convert(::Type{Vector}, X::DataValueVector{T}) where T in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/array/primitives.jl:283 invalidated:
   mt_backedges: 1: signature Tuple{typeof(convert), Type{Vector}, Any} triggered MethodInstance for Pkg.REPLMode.Command(::Pkg.REPLMode.CommandSpec, ::Dict{Symbol, Any}, ::Any) (1 children)
                 2: signature Tuple{typeof(convert), Type{Vector}, Any} triggered MethodInstance for Pkg.REPLMode.Command(::Nothing, ::Dict{Symbol, Any}, ::Any) (12 children)
   backedges: 1: superseding convert(::Type{T}, a::AbstractArray) where T<:Array in Base at array.jl:617 with MethodInstance for convert(::Type{Vector}, ::AbstractArray) (2 children)

 inserting similar(x::Array, ::Type{DataValue{T}}, dims::Tuple{Vararg{Int64, N}} where N) where T in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/array/primitives.jl:16 invalidated:
   mt_backedges: 1: signature Tuple{typeof(similar), Vector, Any, Tuple{Int64}} triggered MethodInstance for similar(::Vector, ::Tuple{Base.OneTo{Int64}}) (2 children)
   backedges: 1: superseding similar(a::Array, T::Type, dims::Tuple{Vararg{Int64, N}}) where N in Base at array.jl:378 with MethodInstance for similar(::Vector{Pair{DataType, Function}}, ::DataType, ::Tuple{Int64}) (1 children)
              2: superseding similar(a::Array, T::Type, dims::Tuple{Vararg{Int64, N}}) where N in Base at array.jl:378 with MethodInstance for similar(::Vector{Any}, ::DataType, ::Tuple{Int64}) (1 children)
              3: superseding similar(a::Array, T::Type, dims::Tuple{Vararg{Int64, N}}) where N in Base at array.jl:378 with MethodInstance for similar(::Vector, ::Type, ::Tuple{Int64}) (1 children)
              4: superseding similar(a::Array, T::Type, dims::Tuple{Vararg{Int64, N}}) where N in Base at array.jl:378 with MethodInstance for similar(::Array, ::DataType, ::Tuple{Int64}) (2 children)
              5: superseding similar(a::Array, T::Type, dims::Tuple{Vararg{Int64, N}}) where N in Base at array.jl:378 with MethodInstance for similar(::Array, ::Type, ::Tuple{Int64}) (2 children)
              6: superseding similar(a::Array, T::Type, dims::Tuple{Vararg{Int64, N}}) where N in Base at array.jl:378 with MethodInstance for similar(::Vector{Pair{DataType, Function}}, ::Type, ::Tuple{Int64}) (6 children)
              7: superseding similar(a::Array, T::Type, dims::Tuple{Vararg{Int64, N}}) where N in Base at array.jl:378 with MethodInstance for similar(::Vector{Any}, ::Type, ::Tuple{Int64}) (11 children)
   30 mt_cache

 inserting !(x::DataValue{T}) where T<:Number in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/scalar/core.jl:203 invalidated:
   mt_backedges:  1: signature Tuple{typeof(!), Any} triggered MethodInstance for (::Base.var"#97#98"{typeof(iszero)})(::Any) (0 children)
                  2: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Any, ::Int64) (0 children)
                  3: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Int64, ::Any) (0 children)
                  4: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::AbstractFloat, ::AbstractFloat) (0 children)
                  5: signature Tuple{typeof(!), Any} triggered MethodInstance for Pkg.LazilyInitializedFields.lazy_struct(::Expr) (0 children)
                  6: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Any, ::Type{Float64}) (0 children)
                  7: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool) (0 children)
                  8: signature Tuple{typeof(!), Any} triggered MethodInstance for showerror(::IOContext{Base.TTY}, ::MethodError) (0 children)
                  9: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Tuple{Base.OneTo{Int64}}, ::Any) (0 children)
                 10: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Union{Nothing, Pkg.Types.UpgradeLevel, VersionNumber, String, Pkg.Versions.VersionSpec}, ::Union{Nothing, Pkg.Types.UpgradeLevel, VersionNumber, String, Pkg.Versions.VersionSpec}) (0 children)
                 11: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.Sort.var"#sort!#8"(::Base.Sort.Algorithm, ::typeof(isless), ::typeof(identity), ::Nothing, ::Base.Order.ForwardOrdering, ::typeof(sort!), ::Vector) (0 children)
                 12: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.Sort.var"#sort!#8"(::Base.Sort.Algorithm, ::typeof(isless), ::Function, ::Nothing, ::Base.Order.ForwardOrdering, ::typeof(sort!), ::Vector) (0 children)
                 13: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Any, ::Any) (0 children)
                 14: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Unsigned, ::Int64) (0 children)
                 15: signature Tuple{typeof(!), Any} triggered MethodInstance for ==(::Dict{String, Any}, ::Dict{String, Any}) (0 children)
                 16: signature Tuple{typeof(!), Any} triggered MethodInstance for Pkg.REPLMode._completions(::String, ::Bool, ::Int64, ::Int64) (0 children)
                 17: signature Tuple{typeof(!), Any} triggered MethodInstance for allunique(::AbstractRange) (0 children)
                 18: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Any, ::Char) (0 children)
                 19: signature Tuple{typeof(!), Any} triggered MethodInstance for (::GlobalRef, ::Any) (0 children)
                 20: signature Tuple{typeof(!), Any} triggered MethodInstance for Test.do_test_throws(::Test.ExecutionResult, ::Any, ::Any) (0 children)
                 21: signature Tuple{typeof(!), Any} triggered MethodInstance for Test.eval_test(::Expr, ::Expr, ::LineNumberNode, ::Bool) (0 children)
                 22: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Any, ::Type{Float16}) (0 children)
                 23: signature Tuple{typeof(!), Any} triggered MethodInstance for !=(::Any, ::Type{Float32}) (0 children)
                 24: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.CoreLogging.log_record_id(::Any, ::Any, ::Any, ::Tuple{}) (1 children)
                 25: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.isdelimited(::IOContext{IOBuffer}, ::Pair{Symbol, Any}) (1 children)
                 26: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.isdelimited(::IOContext{IOBuffer}, ::Pair) (1 children)
                 27: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.Docs.moduledoc(::LineNumberNode, ::Module, ::Expr, ::Any, ::Expr) (1 children)
                 28: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.at_disable_library_threading(::LinearAlgebra.var"#249#250") (1 children)
                 29: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.at_disable_library_threading(::Function) (1 children)
                 30: signature Tuple{typeof(!), Any} triggered MethodInstance for REPL.LineEditREPL(::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any) (1 children)
                 31: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.CoreLogging.log_record_id(::Any, ::Any, ::Any, ::Tuple{Any, Vararg{Any}}) (2 children)
                 32: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.Docs.moduledoc(::Any, ::Any, ::Any, ::Any, ::Expr) (2 children)
                 33: signature Tuple{typeof(!), Any} triggered MethodInstance for ==(::Vector{Int64}, ::Array) (2 children)
                 34: signature Tuple{typeof(!), Any} triggered MethodInstance for REPL._trimdocs(::Markdown.MD, ::Bool) (2 children)
                 35: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.CoreLogging.log_record_id(::Any, ::Any, ::Any, ::Any) (3 children)
                 36: signature Tuple{typeof(!), Any} triggered MethodInstance for Base._show_nonempty(::IOContext{Base.TTY}, ::AbstractMatrix, ::String, ::Bool, ::Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}) (3 children)
                 37: signature Tuple{typeof(!), Any} triggered MethodInstance for (::Pkg.REPLMode.var"#command_is_focused#53"{Bool, Int64})() (3 children)
                 38: signature Tuple{typeof(!), Any} triggered MethodInstance for (::Base.var"#38#40")(::Core.MethodMatch) (9 children)
                 39: signature Tuple{typeof(!), Any} triggered MethodInstance for (::Base.var"#isword#489")(::Char) (12 children)
                 40: signature Tuple{typeof(!), Any} triggered MethodInstance for Base.Docs.moduledoc(::LineNumberNode, ::Module, ::Any, ::Any, ::Expr) (15 children)

 inserting ==(a::T1, b::DataValue{T2}) where {T1, T2} in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/scalar/core.jl:224 invalidated:
   backedges: 1: superseding ==(x, y) in Base at Base.jl:116 with MethodInstance for ==(::Base.UUID, ::Any) (8 children)
              2: superseding ==(x, y) in Base at Base.jl:116 with MethodInstance for ==(::Module, ::Any) (12 children)
              3: superseding ==(x, y) in Base at Base.jl:116 with MethodInstance for ==(::Core.TypeName, ::Any) (14 children)
              4: superseding ==(x, y) in Base at Base.jl:116 with MethodInstance for ==(::Method, ::Any) (14 children)
              5: superseding ==(x, y) in Base at Base.jl:116 with MethodInstance for ==(::Symbol, ::Any) (118 children)

 inserting convert(::Type{Any}, ::DataValue{Union{}}) in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/scalar/core.jl:42 invalidated:
   backedges: 1: superseding convert(::Type{Any}, x) in Base at Base.jl:60 with MethodInstance for convert(::Type{Any}, ::Any) (1934 children)
   1 mt_cache

 inserting ==(a::DataValue{T1}, b::T2) where {T1, T2} in DataValues at /home/sethaxen/.julia/packages/DataValues/N7oeL/src/scalar/core.jl:223 invalidated:
   backedges: 1: superseding ==(x, y) in Base at Base.jl:116 with MethodInstance for ==(::Any, ::FileWatching._FDWatcher) (5 children)
              2: superseding ==(x, y) in Base at Base.jl:116 with MethodInstance for ==(::Any, ::Task) (6616 children)
   10 mt_cache
@davidanthoff
Copy link
Member

The question is how to fix this? These methods all are there so that things work correctly...

@svilupp
Copy link

svilupp commented Apr 26, 2023

I'd like to echo @sethaxen 's observation.

I wasn't even aware that I have DataValues in my Manifest, but invalidations analysis revealed a huge number of inv. happening because of DataValues. Just the convert method alone caused >8000 invalidations (see below).

 inserting convert(::Type{Any}, ::DataValues.DataValue{Union{}}) @ DataValues ~/.julia/packages/DataValues/N7oeL/src/scalar/core.jl:42 invalidated:
   backedges: 1: superseding convert(::Type{Any}, x) @ Base Base.jl:63 with MethodInstance for convert(::Type{Any}, ::Any) (8233 children)
              2: superseding convert(::Type{Any}, x) @ Base Base.jl:63 with MethodInstance for convert(::Type{Any}, ::Any) (1 children)
              3: superseding convert(::Type{Any}, x) @ Base Base.jl:63 with MethodInstance for convert(::Type{Any}, ::Any) (1 children)
              4: superseding convert(::Type{Any}, x) @ Base Base.jl:63 with MethodInstance for convert(::Type{Any}, ::Any) (1 children)
              5: superseding convert(::Type{Any}, x) @ Base Base.jl:63 with MethodInstance for convert(::Type{Any}, ::Any) (1 children)
              6: superseding convert(::Type{Any}, x) @ Base Base.jl:63 with MethodInstance for convert(::Type{Any}, ::Any) (1 children)

I'm clueless about how to solve this without breaking things I don't understand, so my temporary solution was:

  • find the direct dependency that links to DataValues.jl - it my case it was StatsPlots.jl
  • I wasn't using anything fancy from StatsPlots.jl, so I simply swapped my package to Plots.jl

The outcome was 2s faster package load.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants