Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1.12'
- '1.12-nightly'
- 'nightly'
os:
- ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[compat]
DocStringExtensions = "0.9"
MethodAnalysis = "0.4"
MethodAnalysis = "0.4, 1"
julia = "1.12"

[extensions]
Expand Down
19 changes: 19 additions & 0 deletions ext/MethodAnalysisExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,23 @@ function MethodAnalysis.methodinstances(info::PkgCacheInfo)
return mis
end

function PkgCacheInspector.count_internal_specializations(info::PkgCacheInfo)
spec_counts = Dict{Module,Int}()

# Get all method instances from the cache
all_mis = methodinstances(info)

# Count method instances by their defining module
for mi in all_mis
if isa(mi, Core.MethodInstance) && isa(mi.def, Method)
method_module = mi.def.module
if method_module in info.modules
spec_counts[method_module] = get(spec_counts, method_module, 0) + 1
end
end
end

return spec_counts
end

end
59 changes: 59 additions & 0 deletions src/PkgCacheInspector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,52 @@ function Base.show(io::IO, info::PkgCacheInfo)
nspecs = sort(collect(nspecs); by=last, rev=true)
nspecs_tot = sum(last, nspecs; init=0)

# Count internal methods and specializations
internal_methods = count_internal_methods(info)
total_internal = sum(values(internal_methods))

# Try to count internal specializations if MethodAnalysis is available
internal_specs = Dict{Module,Int}()
total_internal_specs = 0
internal_specs_sorted = Pair{Module,Int}[]

internal_specs = count_internal_specializations(info)
if internal_specs !== nothing
internal_specs_sorted = sort(collect(internal_specs); by=last, rev=true)
total_internal_specs = sum(last, internal_specs_sorted; init=0)
end

println(io, "Contents of ", info.cachefile, ':')
println(io, " modules: ", info.modules)
!isempty(info.init_order) && println(io, " init order: ", info.init_order)

# Show internal methods
if total_internal > 0
println(io, " ", total_internal, " internal methods")
if length(internal_methods) > 1
print(io, " (")
sorted_internal = sort(collect(internal_methods); by=last, rev=true)
for i = 1:length(sorted_internal)
mod, count = sorted_internal[i]
print(io, i==1 ? "" : ", ", nameof(mod), " ", count)
end
println(io, ")")
end
end

# Show internal specializations
if internal_specs === nothing
println(io, " specializations of internal methods: (requires MethodAnalysis.jl)")
elseif total_internal_specs > 0
print(io, " ", total_internal_specs, " specializations of internal methods ")
for i = 1:min(3, length(internal_specs_sorted))
mod, count = internal_specs_sorted[i]
pct = round(100*count/total_internal_specs; digits=1)
print(io, i==1 ? "(" : ", ", nameof(mod), " ", pct, "%")
end
println(io, length(internal_specs_sorted) > 3 ? ", ...)" : ")")
end

!isempty(info.external_methods) && println(io, " ", length(info.external_methods), " external methods")
if !isempty(info.new_specializations)
print(io, " ", length(info.new_specializations), " new specializations of external methods ")
Expand Down Expand Up @@ -182,6 +225,22 @@ function count_module_specializations(new_specializations)
return modcount
end

# count_internal_specializations is defined in MethodAnalysisExt when MethodAnalysis is loaded
count_internal_specializations(::Any) = nothing

# Count the number of methods defined within each of the package's own modules.
# These are methods that belong to the modules stored in the package image,
# as opposed to external methods which extend functions from other modules.
function count_internal_methods(info::PkgCacheInfo)
method_counts = Dict{Module,Int}()
Base.visit(Core.GlobalMethods) do method
if method.module in info.modules
method_counts[method.module] = get(method_counts, method.module, 0) + 1
end
end
return method_counts
end

function info_cachefile(pkg::PkgId, path::String, depmods::Vector{Any}, image_targets::Vector{Any}, isocache::Bool=false)
if isocache
sv = ccall(:jl_restore_package_image_from_file, Any, (Cstring, Any, Cint, Cstring, Cint), path, depmods, true, pkg.name, false)
Expand Down
2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ module EmptyPkg end
str = sprint(show, info)
@test occursin("relocations", str) && occursin("new specializations", str) && occursin("targets", str)
@test occursin("file size", str)
@test occursin("internal methods", str)
@test occursin("specializations of internal methods", str)

mis = methodinstances(info)
@test eltype(mis) === Core.MethodInstance
Expand Down
Loading