Performance of type annotations

Docs say that type annotations on variables and return types of functions facilitate type inference and performance. But does the opposite hold? If I have a function:

function foo(x)::Number
    if isa(x, Number)
        return x
    else
        return 0
    end
end

Will the convert(Number, ...) method be called on the return value of foo, or it will be a no-op, for it is clear that both x and 0 are Numbers?

In general, if I have a variable with type annotation, is convert called at every assignment to the variable or it optimized away whenever type inference is sure about the type of RHS?

1 Like

Julia has excellent tools to answer those questions :slight_smile:
E.g. use @code_warntype and @code_lowered to figure out what happens (you can use ?@code_lowered in the REPL to get the doc string for those macros):


julia> function foo(x)::Number
           if isa(x, Number)
               return x
           else
               return 0
           end
       end
foo (generic function with 1 method)

julia> @code_lowered foo(1)
CodeInfo(:(begin 
        nothing
        SSAValue(0) = Main.Number
        unless x isa Main.Number goto 6 # line 3:
        return (Core.typeassert)((Base.convert)(SSAValue(0), x), SSAValue(0))
        6:  # line 5:
        return (Core.typeassert)((Base.convert)(SSAValue(0), 0), SSAValue(0))
    end))

julia> @code_warntype foo(1)
Variables:
  #self# <optimized out>
  x::Int64

Body:
  begin  # line 3:
      return x::Int64 # line 5:
  end::Int64

julia> @code_warntype foo(1.0)
Variables:
  #self# <optimized out>
  x::Float64

Body:
  begin  # line 3:
      return x::Float64 # line 5:
  end::Float64

julia> @code_warntype foo("1")
Variables:
  #self# <optimized out>
  x <optimized out>

Body:
  begin 
      goto 3 # line 3:
      3:  # line 5:
      return 0
  end::Int64

So Julia seems to turn each return into convert(Number, x)::Number. The type assert and convert get inlined and removed.

4 Likes

@sdanisch Indeed, thanks a lot!