Type Stability in Julia: Avoiding Performance Pathologies in JIT Compilation
arxiv.org
arxiv.org
I am certain I am somewhat wrong in this description, but I would love to see a writeup of the whole story and how both sides (the devs and the scientists) lived through it.
A "solution" to this conundrum is to have big integers by default, which sadly isn't feasible for performance reasons - you can't then take advantage of hardware, because every operation necessarily has to do more work than would be required for machine integers.
--
To add on to this, when encountering overflow (which doesn't happen often in the first place), it's usually sufficient to go for 128 bit integers first instead of jumping directly to big integers. They're still quite a bit faster and offer a much larger space to work with.
Test.@inferred is not quite what is needed:
function foo(x)
s = 0
# better use a zero of the same type than x
# s = zero(x)
for y in x
s += y
end
return s
end
Test.@inferred Float64 foo(12.1)
This test succeeds even if code is type-unstableIt recently got support on vscode.
What was available in Julia before (things like @code_typed) are only applicable locally, so there is only limited benefit. Because linters have dramatically improved in recent years, it feels like Julia was lagging behind until recently.
Actually thinking about it, Julia could use something like refinement types ala Liquidhaskell: http://ucsd-progsys.github.io/liquidhaskell-tutorial/Tutoria...
Generally, several well-known OOP design patterns would naturally lead to instability. In turn, those patterns can be handy to solve certain typical problems. If you have such a problem at hand, you have a choice: either do a well-known thing and embrace instability (which is actually not always all that harmful for performance), or get out of your way and torture your code to make it stable…
btw rust-miniscript is a nice example of a type stable parser :)
Rust is an interesting example, maybe I should look into the library. But the compilation model is very different from probably any JIT, including Julia. Optimizations too. For one, unions (enums) in Rust would have much less profound impact on possible optimizations and therefore performance.
Calling code would, of course, have to destructure the return. But destructures of a return value can be very efficient using match (jump tables internally where possible).
i don't care about the performance as much the correctness :)
--
EDIT: Nevermind, found it in the zip!
What do you think of JET.jl?
Tension between Method ambiguities and desire for traits or multiple inheritance is something discussed in the community. Has your group given any thought to this?
Thanks !
> Informally, a function is type stable if the type of the output depends only on the types of the inputs, not their values.
This line reminds me of (the opposite of) dependent-type. But I think that intuition may not be useful or relevant for understanding here?