Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a list of all the function signatures that have been compiled for a generic function

Tags:

julia

The Julia JIT compiler compiles separate versions of generic functions for each unique function signature that gets called at the REPL. For example, if foo is defined as

foo(x, y) = (x * y) ^ 2

then calling foo(2, 3) and foo("a", "b") will compile two different versions of foo that correspond to the signatures foo(::Int, ::Int) and foo(::String, ::String), respectively. Is there a way to get a list of the different function signatures that have been compiled for a generic function?

I know about the methods function, but methods only lists the methods of a generic function that have been written by the programmer. And, of course, as the foo example above demonstrates, one method written by a programmer can spawn many separate compiled functions.

I'm just asking this for educational purposes. I don't have any code in which I plan to use the results of a hypothetical function that shows all the function signatures that have been compiled.

like image 349
Cameron Bieganek Avatar asked Oct 07 '20 00:10

Cameron Bieganek


3 Answers

The MethodAnalysis package has tools for this and much more. For example:

julia> foo(x, y) = (x * y) ^ 2
foo (generic function with 1 method)

julia> foo(1,1); foo(1.0, 1);

julia> using MethodAnalysis

julia> methodinstances(foo)
2-element Vector{Core.MethodInstance}:
 MethodInstance for foo(::Int64, ::Int64)
 MethodInstance for foo(::Float64, ::Int64)

In some cases the specializations are not an svec, methodinstances makes it more straightforward to collect them in an easy-to-access format.

like image 141
tholy Avatar answered Oct 13 '22 01:10

tholy


Perhaps there is a nicer way but this for sure works:

julia> foo(1,1);

julia> foo(1.0, 1);

julia> typeof(foo).name.mt.defs.func.specializations
svec(MethodInstance for foo(::Int64, ::Int64), MethodInstance for foo(::Float64, ::Int64), #undef, #undef, #undef, #undef, #undef, #undef)
like image 20
Przemyslaw Szufel Avatar answered Oct 13 '22 02:10

Przemyslaw Szufel


Just to make sure it's mentioned here:

There is another package called LookingGlass.jl, which is quite similar to MethodAnalysis.jl, and provides a function for this too:

julia> foo(x, y) = (x * y) ^ 2
foo (generic function with 1 method)

julia> foo(1,1); foo(1.0, 1);

julia> using LookingGlass

julia> LookingGlass.func_specializations(foo)
Dict{Core.MethodInstance,Method} with 2 entries:
  MethodInstance for foo(::Float64, ::Int64) => foo(x, y) in Main at REPL[4]:1
  MethodInstance for foo(::Int64, ::Int64)   => foo(x, y) in Main at REPL[4]:1

I've wanted to merge LookingGlass.jl together with MethodAnalysis.jl for quite some time, but always too busy. 😅

LookingGlass has other runtime reflection analysis tools, for modules, and functions, and methods, but I think the implementations in MethodAnalysis for this task are more robust, so @tholy's answer is probably best.

like image 4
NHDaly Avatar answered Oct 13 '22 03:10

NHDaly