Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Narrow convert methods to reduce invalidations #172

Merged
merged 1 commit into from
Aug 17, 2021

Conversation

timholy
Copy link
Contributor

@timholy timholy commented Aug 13, 2021

This package caused >1000 invalidations for DifferentialEquations.
The main problem is a pair of convert methods: one is redundant with
a method in Base (and needlessly invalidates some code),
and another intersected with signatures like
convert(Base.SHA1, ::Any) and other crazy types.
The reason is because the T in APL{T} is completely unconstrained,
and consequently it's possible in principle for it to be a
REPLTerminal or a Module or whatever. It didn't seem as if that were
the real intent of the convert method, but I'm just guessing that this won't break anything.

I have not run the full tests locally but 🤞

CC @ChrisRackauckas

Some background in another package: JuliaData/CategoricalArrays.jl#177

This package caused >1000 invalidations for DifferentialEquations.
The main problem is a pair of `convert` methods: one is redundant with
a method in Base (and needlessly invalidates some code),
and another intersected with signatures like
`convert(Base.SHA1, ::Any)` and other crazy types.
The reason is because the `T` in `APL{T}` is completely unconstrained,
and consequently it's possible in principle for it to be a
`REPLTerminal` or a `Module` or whatever. It didn't seem as if that were
the real intent of the convert method.
@@ -73,5 +72,6 @@ function Base.convert(S::Type{<:Union{Number, T}}, p::APL{T}) where T
end
s
end
Base.convert(::Type{T}, p::APL) where T<:Number = scalarize(T, p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this still cause some invalidations ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing serious, if memory serves. The real problem is totally-unconstrained T.

When fixing invalidations, usually I don't like to suggest restrictions on what packages can do (better to fix the code being invalidated). But convert is one of those rare functions that's used in a ton of places with poor inference on the 2nd argument, and it's often used to make inference better. Consequently it's bad to specialize only on the 2nd argument, since so many callers don't know what type their 2nd argument is. It's generally fine if you specialize on the first argument.

You can add more convert methods than this, I just gave one that is needed to pass tests. But keep in mind that the call site could also just call scalarize directly, and that would be the cleanest solution of all (just deleting this method altogether).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks for the detailed explanation. I try to keep the same behavior independently of whether the coefficient is a number or not as the coefficient is for instance sometimes a JuMP expressions which is not a number. Therefore I might remove this convert and see what's break. Meanwhile I'll merge this PR. Thanks!

@blegat blegat merged commit 7ccc7b8 into JuliaAlgebra:master Aug 17, 2021
@timholy timholy deleted the teh/invalidations branch August 18, 2021 09:52
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.

2 participants