@code_warntype does not produce a helpful output when called with keyword arguments

Hello,

I noticed @code_warntype does not produce a helpful output when the function in question has keyword arguments. Is there a way to call @code_warntype, such that we get more information?

Here is a minimal example I could find in julia-1.3.0. The following are two type unstable functions that do exactly the same thing.

function array1(arr)
    if length(arr) > 3
        result = rand(3)
    else
        result = arr
    end
    
    result
end

function array2(arr; Ο΅ = 10e-12)
    if length(arr) > 3
        result = rand(3)
    else
        result = arr
    end
    
    result
end

However, when called with @code_warntype, they return very different outputs.

@code_warntype array1([2,2])

Variables
  #self#::Core.Compiler.Const(array1, false)
  arr::Array{Int64,1}
  result::Union{Array{Float64,1}, Array{Int64,1}}

Body::Union{Array{Float64,1}, Array{Int64,1}}
1 ─      Core.NewvarNode(:(result))
β”‚   %2 = Main.length(arr)::Int64
β”‚   %3 = (%2 > 3)::Bool
└──      goto #3 if not %3
2 ─      (result = Main.rand(3))
└──      goto #4
3 ─      (result = arr)
4 β”„      return result

and

@code_warntype array2([2,2])

Variables
  #self#::Core.Compiler.Const(array2, false)
  arr::Array{Int64,1}

Body::Union{Array{Float64,1}, Array{Int64,1}}
1 ─ %1 = Main.:(var"#array2#9")(1.0e-11, #self#, arr)::Union{Array{Float64,1}, Array{Int64,1}}
└──      return %1

In the case of array1, @code_warntype tells us about internal function calls, such as Main.length, whereas in the case of array2, we only get a single Main.:(var"#array2#9")(1.0e-11, #self#, arr), and no information about what’s happening inside the function.
When trying to understand type instability of complicated functions with keyword arguments, this is a pretty huge roadblock. Is there a way around this?

Thanks in advance!

1 Like

This is an unfortunate limitation of @code_warntype. The standard workaround I believe is to use the package Cthulhu.jl to be able to descend into function calls inside the outermost function. Cthulhu allows you to iteratively diplays code_warntype for functions called by the outermost function.

3 Likes

Ah thanks! I just tested @descend_code_warntype from Chulhu.jl, and it seemed to have worked, though a bit cumbersome to read.

β”‚ ─ %-1  = invoke array2(::Array{Int64,1})::Union{Array{Float64,1}, Array{Int64,1}}
Body::Union{Array{Float64,1}, Array{Int64,1}}
    @ In[5]:12 within `array2'
   β”Œ @ In[5]:12 within `#array2#3'
   β”‚β”Œ @ array.jl:216 within `length'
1 ─││ %1 = Base.arraylen(arr)::Int64
β”‚  β”‚β””
β”‚  β”‚β”Œ @ operators.jl:294 within `>'
β”‚  β”‚β”‚β”Œ @ int.jl:49 within `<'
β”‚  β”‚β”‚β”‚ %2 = Base.slt_int(3, %1)::Bool
β”‚  β”‚β””β””
└──│      goto #3 if not %2
   β”‚ @ In[5]:13 within `#array2#3'
   β”‚β”Œ @ D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.3\Random\src\Random.jl:277 within `rand'
2 ─││ %4 = invoke Random.rand(Random.Float64::Type{Float64}, (3,)::Tuple{Int64})::Array{Float64,1}
β”‚  β”‚β””
└──│      goto #4
3 ─│      nothing
   β”‚ @ In[5]:18 within `#array2#3'
4 β”„β”‚ %7 = Ο† (#2 => %4, #3 => _2)::Union{Array{Float64,1}, Array{Int64,1}}
└──│      goto #5
   β””
5 ─      return %7

You can turn off some of the printouts, check the bottom of the printout for keyboard shortcuts to disable some information. I seem to recall that I usually typed d to turn off debug info

2 Likes