Given a function f
and its arguments args
, Is there a faster way to get corresponding CodeInfo
than code_lowered(f, map(typeof, args))
? I don’t care about type inference and compiler optimizations - in fact, the closer to the original method definition, the better
I think code_lowered
is really bare minimal already, it comes down to (as you probably have looked at):
julia> m = first(Base.method_instances(+, (Int, Int))).def
julia> Base.uncompressed_ir(m)
CodeInfo(
@ int.jl:87 within `+`
1 ─ %1 = Base.add_int(x, y)
└── return %1
)
and looks like if the function is not generated, the uncompressed_ir
is just calling:
_uncompressed_ir(m::Method, s::Array{UInt8,1}) = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), m, C_NULL, s)::CodeInfo
on the byte vector of m.def.source
1 Like
Huh, actually, if we use only the methods you showed and skip a few checks you avoided, we get a good performance improvement for the first call on the first function:
# each line ran in a fresh Julia session
@time for fn in fns get_code_info(fn, 1.0) end # 0.29s
@time for fn in fns get_code_info2(fn, 1.0) end # 0.09
@time get_code_info(sin, 1.0) # 0.23
@time get_code_info2(sin, 1.0) # 0.08
where:
function get_code_info(f, args...)
types = map(typeof, args)
cis = code_lowered(f, types)
if isempty(cis)
arg_type_str = join(types, ", ")
error("Cannot get CodeInfo for $f($arg_type_str)")
end
return cis[1]
end
function get_code_info2(f, args...)
types = map(typeof, args)
mis = Base.method_instances(f, types)
if isempty(mis)
arg_type_str = join(types, ", ")
error("Cannot get CodeInfo for $f($arg_type_str)")
end
m = first(mis).def
ci = Base.uncompressed_ir(m)
return ci
end
Anyway, the added latency of code_info()
only shows up during the very first invocation, so probably it’s not worth the complexity. Thanks for confirming my expectations!
1 Like