Hacker News new | ask | show | jobs
by borodi 1239 days ago
One interesting thing is that if julia can prove what types a function will be called with at compile time, it doesn't have to do dynamic dispatch, so it has no overhead. It's what the julia folks call type-stable code
1 comments

If ifs and buts were candy and nuts...
This becomes an important part of optimizing Julia code. There is some tooling for this. Below, identity is a type stable function because we know that an Int64 argument results in a Int64 output. The macro code_warntype reveals the type analysis:

``` julia> @code_warntype identity(5) MethodInstance for identity(::Int64) from identity(x) @ Base operators.jl:513 Arguments #self#::Core.Const(identity) x::Int64 Body::Int64 1 ─ nothing └── return x ```

This is type unstable and results in dynamic dispatch because we are not sure if the argument to identity will be an Int64 or a Float64.

``` julia> f(x) = identity(x ≥ 0 ? x : x + 0.0) f (generic function with 1 method)

julia> @code_warntype f(5) MethodInstance for f(::Int64) from f(x) @ Main REPL[4]:1 Arguments #self#::Core.Const(f) x::Int64 Locals @_3::Union{Float64, Int64} Body::Union{Float64, Int64} 1 ─ %1 = (x ≥ 0)::Bool └── goto #3 if not %1 2 ─ (@_3 = x) └── goto #4 3 ─ (@_3 = x + 0.0) 4 ┄ %6 = @_3::Union{Float64, Int64} │ %7 = Main.identity(%6)::Union{Float64, Int64} └── return %7 ```

Now with better formatting...

This becomes an important part of optimizing Julia code. There is some tooling for this. Below, identity is a type stable function because we know that an Int64 argument results in a Int64 output. The macro code_warntype reveals the type analysis:

  julia> @code_warntype identity(5)
  MethodInstance for identity(::Int64)
    from identity(x) in Base at operators.jl:526
  Arguments
    #self#::Core.Const(identity)
    x::Int64
  Body::Int64
  1 ─     return x


  julia> f(x) = identity(x ≥ 0 ? x : x + 0.0) 
  f (generic function with 1 method)

  julia> @code_warntype f(5)
  MethodInstance for f(::Int64)
    from f(x) in Main at REPL[6]:1
  Arguments
    #self#::Core.Const(f)
    x::Int64
  Locals
    @_3::Union{Float64, Int64}
  Body::Union{Float64, Int64}
  1 ─ %1 = (x ≥ 0)::Bool
  └──      goto #3 if not %1
  2 ─      (@_3 = x)
  └──      goto #4
  3 ─      (@_3 = x + 0.0)
  4 ┄ %6 = @_3::Union{Float64, Int64}
  │   %7 = Main.identity(%6)::Union{Float64, Int64}
  └──      return %7