JuliaMath / JuliaMath/FixedPointNumbers.jl

Loading FixedPointNumbers invalidates ~7,700 precompiled method instances (7x slower first mtkcompile)

Aperta
#331 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Julia
Stelle
95
Fork
38
Merge medio
13m
PR unite (30g)
2

Descrizione

## Summary

Loading FixedPointNumbers into a session that already has ModelingToolkit loaded invalidates
**7,708 precompiled method instances** and makes the first `mtkcompile` call take **23.59 s
instead of 0.04 s** — a huge slowdown in a script that never uses a fixed-point number.

Most users meet this indirectly: ColorTypes/Colors depend on FixedPointNumbers, so any
Makie-based plotting next to ModelingToolkit pays this cost on the first model build.

## MWE

```julia
# mwe.jl
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
if get(ENV, "LOAD_FPN", "0") == "1"
@eval using FixedPointNumbers # <-- the only difference
end
@variables x(t)=1.0 y(t)=0.0
@named sys = System([D(x) ~ y, D(y) ~ -x], t)
t0 = time(); mtkcompile(sys); println("mtkcompile: ", round(time()-t0, digits=2), " s")
```
```
(test) pkg> st
Status `~/test/Project.toml`
[53c48c17] FixedPointNumbers v0.9.1
[961ee093] ModelingToolkit v11.41.0
```

```
$ julia --startup-file=no --project=. mwe.jl
mtkcompile: 0,04 s

$ LOAD_FPN=1 julia --startup-file=no --project=. mwe.jl
mtkcompile: 23.59 s
```

As a control, loading a package of comparable size that does not add methods to Base
generics (`using LaTeXStrings`) leaves the time unchanged at 0.04 s, so this is not the
general cost of loading a package.

## Attribution

```julia
using SnoopCompileCore
using ModelingToolkit
invs = @snoop_invalidations using FixedPointNumbers;
using SnoopCompile
length(uinvalidated(invs)) # 7708, from 15 culprit methods
```

Ranked by `countchildren`:

| children | method |
|---:|:---|
| 14312 | `promote_rule(::Type{Fixed{T1,f1}}, ::Type{Fixed{T2,f2}}) where {T1,T2,f1,f2}` — `src/fixed.jl:199` |
| 3556 | `length(r::AbstractUnitRange{N}) where {T<:Unsigned, N<:Normed{T}}` — `src/normed.jl:304` |
| 3089 | `ceil(::Type{Ti}, x::Normed) where Ti<:Integer` — `src/normed.jl:277` |
| 1668 | `showarg(io::IO, a::Array{T}, toplevel) where T<:FixedPoint` — `src/FixedPointNumbers.jl:279` |
| 403 | `reduce_first(::typeof(Base.add_sum), x::FixedPoint)` — `src/FixedPointNumbers.jl:296` |
| 109 | `-(x::X) where X<:FixedPoint` — `src/FixedPointNumbers.jl:233` |

None of these are type piracy — every one is dispatching on a FixedPointNumbers type. The
cost seems to come from adding methods to widely-inferred Base generics (`promote_rule`,
`length`, `ceil`, `convert`), which discards inference results in already-loaded packages
that call those generics on non-concrete argument types.

## Question

Is there room to narrow any of these signatures, or is this something that has to be fixed
on the consuming side (or in Base)? I am mostly filing this for the record, since the
measured impact is large and I could not find an existing issue about it. Happy to run
further measurements if that helps.

## Versions

Julia 1.12.7 (Linux, x86_64), FixedPointNumbers 0.8.6, ModelingToolkit 11.17.0,
SnoopCompile 3.2.9.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Start with mwe.jl and the SnoopCompile invalidation measurements, then inspect the listed methods in src/fixed.jl, src/normed.jl, and src/FixedPointNumbers.jl. Compare narrower signatures or other changes against the 7,708 invalidations and mtkcompile timings, while checking that FixedPointNumbers behavior remains correct; done means reducing the loading impact without regressions.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
julia
Ambito
performance
Tipo di issue
Bug
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
42/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.