Skip to content

Cut ~57% of load-time invalidations#1344

Open
Beforerr wants to merge 1 commit into
JuliaArrays:masterfrom
Beforerr:reduce-invalidations
Open

Cut ~57% of load-time invalidations#1344
Beforerr wants to merge 1 commit into
JuliaArrays:masterfrom
Beforerr:reduce-invalidations

Conversation

@Beforerr
Copy link
Copy Markdown

@Beforerr Beforerr commented May 17, 2026

Three small dispatch tweaks that drop invalidated MethodInstances from ~2030 to ~875 on Julia 1.12, with no behaviour change and all tests passing. Related to #1074.

What changed

1. eachindex(::IndexLinear, ::StaticArray) → restrict to rank N ≥ 2.

Base's eachindex(::IndexLinear, ::AbstractVector) = axes1(A) already returns SOneTo for static vectors, so we only need our specialised path for higher ranks. Pinning rank with concrete N (via a Union over 2:32) is what makes Julia's invalidator see Union{} against AbstractVector{X} — a where N clause still intersects because N could be 1. Wipes the entire eachindex invalidation tree (~513 MIs).

2. Drop any(f::Function, ::StaticArray), all(f::Function, ::StaticArray), count(f, ::StaticArray).

Base's any(f, A)_any(f, A, dims)mapreduce(f, |, A; ...). Since we already specialise mapreduce for StaticArray, the fast path is preserved without the extra method. The dropped ::Bool cast was defensive and isn't needed when eltypes are statically known; init=false matches the default _InitialValue behaviour for |/&/+. Removes the biggest single invalidation source (~640 MIs from compiler-internal any(::Function, ::AbstractArray) callers).

3. setindex!(::TrivialView, inds...)setindex!(::TrivialView, v, inds...).

The old signature was missing the value slot, so it superseded Base.setindex!(::AbstractArray, v, I...) more aggressively than needed. -4 MIs.

Numbers (Julia 1.12.6, this branch)

before after
invalidation trees 17 15
invalidated MIs ~2030 ~875 (-57%)
@time_imports ~85 ms ~80 ms

Load time is dominated by C-level method-table registration so the wall-clock win is small, but downstream packages that hit AbstractVector or any(::Function, ::AbstractArray) will see less recompilation triggered by using StaticArrays.

Tested

Full Pkg.test() suite passes locally.

Three small signature tweaks that cut invalidated MIs ~57% (2030 -> 875)
and remove two whole invalidation trees:

- `eachindex(::IndexLinear, ::StaticArray)`: narrow to rank N >= 2 via a
  `Union{StaticArray{<:Tuple,T,N} where T for N in 2:32...}`. Vectors fall
  through to `Base.axes1` which already returns `SOneTo`. Concrete `N`
  in the signature is what makes the invalidator see `Union{}` against
  `AbstractVector{X}`; a `where N` clause does not.

- `any`/`all`/`count` with a function argument: drop the specialised
  methods. Base routes `any(f, A)` through `mapreduce(f, |, A)`, and
  we already specialise `mapreduce` for `StaticArray`, so the fast
  path is preserved. The removed `::Bool` cast was defensive and not
  needed for static eltypes; the explicit `init=false` matches the
  default for `|`/`&`/`+`.

- `setindex!(::TrivialView, inds...)`: add the missing `v` slot.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Beforerr Beforerr changed the title Cut ~57% of load-time invalidations (#1074) Cut ~57% of load-time invalidations May 17, 2026
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

Successfully merging this pull request may close these issues.

1 participant