SymbolicUtils.jl icon indicating copy to clipboard operation
SymbolicUtils.jl copied to clipboard

Symbolics causing a lot of method invalidations

Open GlenHertz opened this issue 1 year ago • 0 comments

cc @oscardssmith

using MyProject went form 12 to 6 seconds by removing the Symbolics dependency. I did a SnoopCompile analysis and the top contributors were related to:

https://github.com/JuliaSymbolics/SymbolicUtils.jl/blob/94e0dd08efa1167930baf7366f1846271fa5b100/src/types.jl#L190-L192

I tried switching the order so the Base.isequal(::Symbolic, ::Symbolic) = false definition was first hoping it wouldn't go into an ambiguous state but that didn't help.

I created a MWE with that seems to give me similar results to when it is in my project:

using SnoopCompile
invalidations = @snoopr begin
    # Your code goes here!
    using Symbolics # all that is needed
    end;
trees = SnoopCompile.invalidation_trees(invalidations);
@show length(SnoopCompile.uinvalidated(invalidations)) # show 3500 total invalidations
show(trees[end]) # show the most invalidated method
show(trees[end-1]) # show the most invalidated method
show(trees[end-2]) # show the most invalidated method
# Count number of children (number of invalidations per invalidated method)
n_invalidations = map(trees) do methinvs
    SnoopCompile.countchildren(methinvs)
end
import Plots
Plots.plot(
    1:length(trees),
    n_invalidations;
    markershape=:circle,
    xlabel="i-th method invalidation",
    label="Number of children per method invalidations"
)

The one with the most invalidations is:

julia> show(trees[end]) # show the most invalidated method
inserting isequal(x, ::SymbolicUtils.Symbolic) @ SymbolicUtils ~/.julia/packages/SymbolicUtils/qulQp/src/types.jl:64 invalidated:
   backedges: 1: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::Distributed.RRID, ::Any) (1 children)
              2: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::Tuple{Module, String, Float64}, ::Any) (1 children)
              3: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::WeakRef, ::Any) (2 children)
              4: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::Type, ::Any) (5 children)
              5: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::Distributed.Future, ::Any) (31 children)
              6: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::Char, ::Any) (38 children)
              7: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::String, ::Any) (577 children)
false

Next:

julia> show(trees[end-1])
inserting isequal(::SymbolicUtils.Symbolic, x) @ SymbolicUtils ~/.julia/packages/SymbolicUtils/qulQp/src/types.jl:63 invalidated:
   mt_backedges: 1: signature isequal(x, y) @ Base operators.jl:133 (formerly isequal(x, y) @ Base operators.jl:133) triggered MethodInstance for ==(::WeakRef, ::Symbol) (0 children)
                 2: signature isequal(x, y) @ Base operators.jl:133 (formerly isequal(x, y) @ Base operators.jl:133) triggered MethodInstance for setindex!(::Dict, ::typeof(Latexify.mdtable), ::Symbol) (0 children)
                 3: signature isequal(x, y) @ Base operators.jl:133 (formerly isequal(x, y) @ Base operators.jl:133) triggered MethodInstance for setindex!(::Dict, ::typeof(Latexify._latexinline), ::Symbol) (0 children)
   backedges: 1: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::Any, ::String) (46 children)
              2: superseding isequal(x, y) @ Base operators.jl:133 with MethodInstance for isequal(::Any, ::Char) (224 children)
   30 mt_cache
false

But in my project the output is about 5 times larger.

GlenHertz avatar Jan 09 '23 20:01 GlenHertz