How Do You Actually Check for Type Stability in Julia?

Hey everyone,

I have been diving into Julia lately & loving the speed but I am still wrapping my head around some of the concepts— type stability. I have heard it is a big deal for performance but I am not totally sure how to tell if a function is type-stable or not.

Also I have tried using @code_warntype; but the output can be pretty intimidating. All those red and green highlights feel more such as a warning sign than something helpful :joy:

What should I look for in the @code_warntype output?
Any simple examples of bad vs good type stability?
Are there tools or tricks to make this easier to understand?

Totally different note but I have been using Julia alongside Python lately while preparing some[Python interview questions & I am starting to appreciate both for different strengths.

Thank you…:slight_smile:

4 Likes

If all you want is a simple yes/no, @inferred is what you want. e.g.

import Test: @inferred
julia> f(x) = x>0 ? 1 : 1.0
f (generic function with 2 methods)

julia> @inferred f(1)
ERROR: return type Int64 does not match inferred return type Union{Float64, Int64}

If you then want to dig in, @code_warntype and Cthulhu.jl are the way to go. The way to read them is that red means you’ve found something type unstable. Green is type stable (and yellow is a small union which you can usually treat as green, but not always)

11 Likes

It’s important to understand that type-stability is not a well-defined term. To quote from https://arxiv.org/pdf/2109.01950

Effectively, there are two competing, type-related properties of function bodies. To address this confusion, we define and refer to them using two distinct terms:
type stability is when a function’s return type depends only on its argument types, and
type groundedness is when every variable’s type depends only on the argument types.

The second term is not widely used in the Julia community but it’s a useful notion nonetheless. For each concept, there is a corresponding set of tools:

  • Type stability: Test.@inferred, DispatchDoctor.jl
  • Type groundedness: @code_warntype (only for one level of nesting), JET.jl and Cthulhu.jl (for arbitrary nested functions)
5 Likes

I’ve heard many variations of the term “stability” to describe that paper’s definition of groundedness, and we want that more; in an extreme case, we can convert the return value to an argument type for trivial type stability, and we’d still suffer all the performance drawbacks of the poorly inferred local variables (and expressions, the paper is including those in “variable’s”). On top of that, type groundedness in a method call doesn’t imply groundedness of the callees; I’m not even sure if there’s any consistent term for that kind of recursive groundedness, but that’s the aim for eliminating all unnecessary type checking.

1 Like

The link to the paper appears to be broken. Do you have a working link?

I agree that what we want is recursive type-groundedness.

That was just Discourse including the subsequent colon by default into the link, so I removed it. The link should be working now.

This also misses small union optimizations where the types can vary depending on values, but for each variable you at least know a small set of concrete type options.

1 Like