Skip to content

Too many MethodInstances #2829

@odow

Description

@odow

Check this out:

Image
import MathOptInterface as MOI

function get_method_instances(x::Core.MethodInstance, ret::Vector{Any})
    push!(ret, x)
    return ret
end

function get_method_instances(x::Core.SimpleVector, ret::Vector{Any})
    for instance in x
        if instance === nothing
            break
        end
        push!(ret, instance)
    end
    return ret
end

function get_method_instances(mod::Module, ret::Vector{Any} = Any[])
    for name in names(mod; all = true)
        f = getfield(mod, name)
        if f === mod
            continue
        elseif f isa Module
            get_method_instances(f, ret)
        elseif  !(f isa Function)
            continue
        end
        for m in methods(f)
            get_method_instances(m.specializations, ret)
        end
    end
    return ret
end
before = get_method_instances(MOI)
include("test/runtests.jl")
after = get_method_instances(MOI)
function get_methods(mod::Module, ret::Vector{Any} = Any[])
    for name in names(mod; all = true)
        f = getfield(mod, name)
        if f === mod
            continue
        elseif f isa Module
            get_methods(f, ret)
        elseif  !(f isa Function)
            continue
        end
        for m in methods(f)
            push!(
                ret,
                m => get_method_instances(m.specializations, Any[])
            )
        end
    end
    return ret
end
ret = get_methods(MOI);
sort!(ret, by = x -> length(x[2]));
import Plots
data = filter!(>(0), length.(last.(ret)))
plt = Plots.plot(
    data,
    1:length(data);
    xscale = :log10,
    color = "#cb3c33",
    width = 3,
    legend = false,
    xlabel = "Number of MethodInstances",
    ylabel = "Method",
    title = "Cumulative distribution of |MethodInstances|",
    dpi = 300,
)
Plots.savefig(plt, "/tmp/method_instances.png")

Running the tests creates 379,000 method instances:

julia> length(before)
3269

julia> length(after)
381680

There are 17,515 different specialisations of supports_constraint:

julia> counts = [a => length(b) for (a, b) in ret];

julia> counts[end]
supports_constraint(::Type{<:MathOptInterface.Bridges.Constraint.AbstractBridge}, ::Type{<:MathOptInterface.AbstractFunction}, ::Type{<:MathOptInterface.AbstractSet}) @ MathOptInterface.Bridges.Constraint ~/git/jump-dev/MathOptInterface/src/Bridges/Constraint/bridge.jl:38 => 17515

Even 100 methods in, there are 766 different method instances for add_constraints:

julia> counts[end - 99]
add_constraints(model::MathOptInterface.ModelLike, funcs, sets) @ MathOptInterface ~/git/jump-dev/MathOptInterface/src/constraints.jl:269 => 766

I wonder if we should @nospecialize a few of the larger ones.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions