Polynomials.jl: `Base.promote(p::P, q::Q)` in `@poly_register` invalidates ~20,600 method instances on load
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 62/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Ambito
- performance
Direzione di ricerca
Leggi src/abstract-polynomial.jl intorno alla riga 277 ed esamina l’espansione di @poly_register e i metodi promote_rule esistenti. Riproduci l’invalidazione con il comando fornito SnoopCompileCore.@snoop_invalidations in una sessione con un pacchetto di grandi dimensioni caricato, quindi rimuovi il metodo ridondante Base.promote e confronta il comportamento. Il lavoro è terminato quando la promozione continua a funzionare per i tipi di polinomi registrati e il caricamento non causa più le invalidazioni segnalate.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Target: https://github.com/JuliaMath/Polynomials.jl (observed on v4.1.3; the line is still present on master as of 2026-10-19).
What happens
src/abstract-polynomial.jl:277 (inside macro poly_register):
Base.promote(p::P, q::Q) where {B, X, T, P <:$poly{B,T,X}, Q <: $poly{B,T,X}} = p,q
The macro is expanded for six container types (MutableDensePolynomial, MutableDenseViewPolynomial, MutableDenseLaurentPolynomial, ImmutableDensePolynomial, MutableSparsePolynomial, MutableSparseVectorPolynomial), so loading Polynomials adds six 2-argument methods to Base.promote.
Base.promote with two arguments has only two methods in Base (promote(x, y) and promote(x::T, y::T, zs::T...)). Under the default max_methods = 3, every call promote(a, b) that inference sees with non-concrete argument types therefore gets a precise edge to those two methods. The first new 2-arg promote method intersects Tuple{typeof(promote), Any, Any} and invalidates all of those callers and, transitively, everything inferred on top of them.
Measured in a Julia 1.13.2 session whose sysimage contains ModelingToolkit 11.45 / Symbolics 7.45 / SciMLBase 3.57, using SnoopCompileCore.@snoop_invalidations:
20637 promote(p::P, q::Q) where {B, X, T, P<:MutableSparsePolynomial{B,T,X}, Q<:MutableSparsePolynomial{B,T,X}} @ Polynomials src/abstract-polynomial.jl:277
90 adjoint(A::VecOrMat{<:AbstractPolynomial}) @ Polynomials src/common.jl:546
81 collect(::Type{T}, p::MutableSparseVectorPolynomial) where T @ Polynomials src/polynomial-container-types/mutable-sparse-vector-polynomial.jl:91
15 Symbol(::Polynomials.Var{T}) where T @ Polynomials src/abstract.jl:11
Polynomials accounts for 20,823 of the 30,680 invalidated method instances in that session (68%). Whichever of the six promote methods is inserted first takes the whole count; the other five find nothing left to invalidate. Recompiling the invalidated ModelingToolkit mtkcompile pipeline afterwards costs ~35 s of wall time on the first model compile in that process.
Why the method is unnecessary
P <: poly{B,T,X} and Q <: poly{B,T,X} with poly a concrete 3-parameter struct forces P === Q === poly{B,T,X}. Base already has promote(x::T, y::T, zs::T...) where {T} = (x, y, zs...), which returns (p, q) for that case and is more specific than the generic promote(x, y). The Polynomials method is a behavioural no-op.
Proposed fix
Delete the Base.promote line from @poly_register (keep the two promote_rule methods, which are not on an invalidation-prone function). A one-line change, no observable behaviour change.
Smaller follow-ups from the same measurement:
LinearAlgebra.adjoint(A::VecOrMat{<:AbstractPolynomial})(90): consideradjoint(A::Vector{<:AbstractPolynomial})/adjoint(A::Matrix{<:AbstractPolynomial})as two methods, or drop it.Base.collect(::Type{T}, p::MutableSparseVectorPolynomial)(81):collect(::Type, ::Any)call sites carry edges; a non-Base name (coeffs) avoids it.
How to reproduce
using SnoopCompileCore
invs = @snoop_invalidations using Polynomials
using SnoopCompile; trees = invalidation_trees(invs); trees[end]
in a session where ModelingToolkit (or any large package that calls promote generically) is already loaded.
🤖 Posted for @pankgeorg by an AI agent — harness: Claude Code 2.1.304 · model: claude-fable-5-1
Session: local Claude Code session 4d6ce0ef-76db-4236-95e4-ec740bb4651c
- Lingua principale
- Julia
- Stelle
- 321
- Fork
- 81
- Merge medio
- 10h 1m
- PR unite (30g)
- 5
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di JuliaMath/Polynomials.jl
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 83/100
JuliaMath/Polynomials.jl#647 ·
-
tagbot-manual
Difficoltà 2/5 1-3 ore Idoneità per principianti 35/100
JuliaMath/Polynomials.jl#627 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 38/100
JuliaMath/Polynomials.jl#620 · 6 commenti ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
JuliaMath/Polynomials.jl#585 · 7 commenti ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 48/100
JuliaMath/Polynomials.jl#584 ·
Tutte le issue di JuliaMath/Polynomials.jl
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
legend-exp/LegendDataManagement.jl#232 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
EnzymeAD/Reactant.jl#3569 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 90/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 76/100