Skip to content

Too many MethodInstances #2829

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions