Dictionaries.jl
Dictionaries.jl copied to clipboard
Significant method invalidations for `in` with Julia 1.11
I'm seeing the following SnoopCompile output:
inserting in(inds::Dictionaries.ReverseIndices{I, Inds} where Inds<:Dictionaries.AbstractIndices{I}, i::I) where I @ Dictionaries ~/.julia/packages/Dictionaries/RaTRN/src/reverse.jl:7 invalidated:
backedges: 1: superseding in(x, s::Set) @ Base set.jl:92 with MethodInstance for in(::Any, ::Set{T} where T<:Integer) (1 children)
3: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::NTuple{5, Symbol}) (1 children)
4: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{String, String, String, Nothing}) (1 children)
5: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::NTuple{8, Symbol}) (1 children)
6: superseding in(x, itr) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Array{String}) (1 children)
7: superseding in(x, itr) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Base.Generator{I, DataFrames.var"#941#943"} where I<:(Base.Iterators.Filter{DataFrames.var"#942#944"})) (1 children)
10: superseding in(k, v::Base.KeySet{<:Any, <:IdDict}) @ Base iddict.jl:182 with MethodInstance for in(::Any, ::Base.KeySet{Any, IdDict{Any, Nothing}}) (2 children)
11: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{String, String, String}) (2 children)
12: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{}) (2 children)
13: superseding in(x, itr) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Vector{Any}) (2 children)
14: superseding in(x, s::Set) @ Base set.jl:92 with MethodInstance for in(::Any, ::Set{<:Union{Missing, Integer}}) (3 children)
15: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{Symbol, Symbol, Symbol}) (3 children)
17: superseding in(key, v::Base.KeySet{<:Any, <:Dict}) @ Base dict.jl:549 with MethodInstance for in(::Any, ::Base.KeySet{String, Dict{String, Tuple{Any, Any}}}) (4 children)
18: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{Symbol, Symbol}) (5 children)
19: superseding in(x, itr) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::String) (7 children)
20: superseding in(x, s::Set) @ Base set.jl:92 with MethodInstance for in(::Any, ::Set) (11 children)
21: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{typeof(+), typeof(*)}) (13 children)
22: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{Nothing, Bool}) (15 children)
23: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{String, String}) (19 children)
24: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{typeof(*), typeof(^)}) (20 children)
25: superseding in(x, itr) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::BitSet) (26 children)
26: superseding in(x, s::Set) @ Base set.jl:92 with MethodInstance for in(::Any, ::Set{Symbol}) (31 children)
27: superseding in(x, itr::Tuple) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Tuple{typeof(+), typeof(*), typeof(^)}) (31 children)
28: superseding in(x, s::IdSet) @ Base idset.jl:44 with MethodInstance for in(::Any, ::IdSet{Dict}) (41 children)
29: superseding in(x, s::Set) @ Base set.jl:92 with MethodInstance for in(::Any, ::Set{Any}) (63 children)
30: superseding in(x, itr) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Vector) (78 children)
31: superseding in(x, itr) @ Base operators.jl:1302 with MethodInstance for in(::Any, ::Vector{Symbol}) (109 children)
32: superseding in(x, s::IdSet) @ Base idset.jl:44 with MethodInstance for in(::Any, ::IdSet{Dict{String}}) (114 children)
33: superseding in(k, v::Base.KeySet{<:Any, <:IdDict}) @ Base iddict.jl:182 with MethodInstance for in(::Any, ::Base.KeySet{Any, IdDict{Any, Any}}) (481 children)
Some lines removed. The last few seem particularly concerning.
Interesting.
Can you write down how to reproduce that output?
This was an entry in the invalidations data harvested using this tutorial.
I ran @snoop_invalidations using X, where X is a package that pulls in Dictionaries. Running it on using Dictionaries may (should?) give you similar data.
It looks like the problem is related to the base methods of in all accepting Any type for the first argument, whereas the Dictionaries method constrains the type of x.
I just noticed these invalidations too, and see two ways to deal with this:
- Avoid invalidations by using another function instead of extending
Base.in(may not be appropriate ifReversedIndicesare meant to be used and follow an interface onBase.in) - Recompile invalidations, as described in this tutorial where we surround the method with
@recompile_invalidations begin ... #= method =# endusing PrecompileTools.
Any thoughts/preferences?
Just wanted to add that the SciML packages depend on https://github.com/SciML/CommonWorldInvalidations.jl these days, which attempts to be "one place" where a bunch of invalidations are dealt with (it uses @recompile_invalidations). One path would be to try to add some methods there and have Dictionaries depend on it.