Skip to content

Commit 66b6a2b

Browse files
show counts of why caches are rejected
1 parent b51b809 commit 66b6a2b

File tree

1 file changed

+70
-11
lines changed

1 file changed

+70
-11
lines changed

base/loading.jl

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,42 @@
33
# Base.require is the implementation for the `import` statement
44
const require_lock = ReentrantLock()
55

6+
mutable struct StaleReasons
7+
invalid_header::Int
8+
empty_file::Int
9+
mismatched_flags::Int
10+
requires_pkgimages::Int
11+
target_mismatch::Int
12+
missing_ocachefile::Int
13+
for_different_id::Int
14+
for_different_buildid::Int
15+
loaded_incompatible::Int
16+
missing_source::Int
17+
wrong_buildid::Int
18+
different_source::Int
19+
uuid_change::Int
20+
unresolvable_depot::Int
21+
missing_sourcefile::Int
22+
include_dependency_mtime_change::Int
23+
include_dependency_fsize_change::Int
24+
include_dependency_fhash_change::Int
25+
invalid_checksum::Int
26+
ocachefile_invalid_checksum::Int
27+
prefs_hash_mismatch::Int
28+
StaleReasons() = new(zeros(21)...)
29+
end
30+
31+
function show(io::IO, reasons::StaleReasons)
32+
first = true
33+
for n in fieldnames(StaleReasons)
34+
f = getfield(reasons, n)
35+
if f > 0
36+
first ? print(io, "$f $n") : print(io, ", $f $n")
37+
first = false
38+
end
39+
end
40+
end
41+
642
# Cross-platform case-sensitive path canonicalization
743

844
if Sys.isunix() && !Sys.isapple()
@@ -1633,11 +1669,11 @@ end
16331669

16341670
# returns `nothing` if require found a precompile cache for this sourcepath, but couldn't load it
16351671
# returns the set of modules restored if the cache load succeeded
1636-
@constprop :none function _require_search_from_serialized(pkg::PkgId, sourcepath::String, build_id::UInt128)
1672+
@constprop :none function _require_search_from_serialized(pkg::PkgId, sourcepath::String, build_id::UInt128; reasons=nothing)
16371673
assert_havelock(require_lock)
16381674
paths = find_all_in_cache_path(pkg)
16391675
for path_to_try in paths::Vector{String}
1640-
staledeps = stale_cachefile(pkg, build_id, sourcepath, path_to_try)
1676+
staledeps = stale_cachefile(pkg, build_id, sourcepath, path_to_try; reasons)
16411677
if staledeps === true
16421678
continue
16431679
end
@@ -2126,11 +2162,11 @@ function _require(pkg::PkgId, env=nothing)
21262162
set_pkgorigin_version_path(pkg, path)
21272163

21282164
pkg_precompile_attempted = false # being safe to avoid getting stuck in a Pkg.precompile loop
2129-
2165+
reasons = StaleReasons()
21302166
# attempt to load the module file via the precompile cache locations
21312167
if JLOptions().use_compiled_modules != 0
21322168
@label load_from_cache
2133-
m = _require_search_from_serialized(pkg, path, UInt128(0))
2169+
m = _require_search_from_serialized(pkg, path, UInt128(0); reasons)
21342170
if m isa Module
21352171
return m
21362172
end
@@ -2166,7 +2202,7 @@ function _require(pkg::PkgId, env=nothing)
21662202
# double-check now that we have lock
21672203
m = _require_search_from_serialized(pkg, path, UInt128(0))
21682204
m isa Module && return m
2169-
compilecache(pkg, path)
2205+
compilecache(pkg, path; reasons)
21702206
end
21712207
cachefile_or_module isa Module && return cachefile_or_module::Module
21722208
cachefile = cachefile_or_module
@@ -2568,17 +2604,17 @@ This can be used to reduce package load times. Cache files are stored in
25682604
`DEPOT_PATH[1]/compiled`. See [Module initialization and precompilation](@ref)
25692605
for important notes.
25702606
"""
2571-
function compilecache(pkg::PkgId, internal_stderr::IO = stderr, internal_stdout::IO = stdout)
2607+
function compilecache(pkg::PkgId, internal_stderr::IO = stderr, internal_stdout::IO = stdout; reasons::Union{StaleReasons,Nothing}=nothing)
25722608
@nospecialize internal_stderr internal_stdout
25732609
path = locate_package(pkg)
25742610
path === nothing && throw(ArgumentError("$pkg not found during precompilation"))
2575-
return compilecache(pkg, path, internal_stderr, internal_stdout)
2611+
return compilecache(pkg, path, internal_stderr, internal_stdout; reasons)
25762612
end
25772613

25782614
const MAX_NUM_PRECOMPILE_FILES = Ref(10)
25792615

25802616
function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, internal_stdout::IO = stdout,
2581-
keep_loaded_modules::Bool = true)
2617+
keep_loaded_modules::Bool = true; reasons::Union{StaleReasons,Nothing}=nothing)
25822618

25832619
@nospecialize internal_stderr internal_stdout
25842620
# decide where to put the resulting cache file
@@ -2595,7 +2631,7 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in
25952631
end
25962632
# run the expression and cache the result
25972633
verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug
2598-
@logmsg verbosity "Precompiling $pkg"
2634+
@logmsg verbosity "Precompiling $pkg (cache misses: $reasons)"
25992635

26002636
# create a temporary file in `cachepath` directory, write the cache in it,
26012637
# write the checksum, _and then_ atomically move the file to `cachefile`.
@@ -3311,21 +3347,25 @@ function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String; stale_age=compilec
33113347
f()
33123348
end
33133349
end
3350+
33143351
# returns true if it "cachefile.ji" is stale relative to "modpath.jl" and build_id for modkey
33153352
# otherwise returns the list of dependencies to also check
3316-
@constprop :none function stale_cachefile(modpath::String, cachefile::String; ignore_loaded::Bool = false)
3353+
@constprop :none function stale_cachefile(modpath::String, cachefile::String; ignore_loaded::Bool = false, reasons=nothing)
33173354
return stale_cachefile(PkgId(""), UInt128(0), modpath, cachefile; ignore_loaded)
33183355
end
3319-
@constprop :none function stale_cachefile(modkey::PkgId, build_id::UInt128, modpath::String, cachefile::String; ignore_loaded::Bool = false)
3356+
@constprop :none function stale_cachefile(modkey::PkgId, build_id::UInt128, modpath::String, cachefile::String;
3357+
ignore_loaded::Bool = false, reasons::Union{StaleReasons,Nothing}=nothing)
33203358
io = open(cachefile, "r")
33213359
try
33223360
checksum = isvalid_cache_header(io)
33233361
if iszero(checksum)
33243362
@debug "Rejecting cache file $cachefile due to it containing an invalid cache header"
3363+
isnothing(reasons) || (reasons.invalid_header += 1)
33253364
return true # invalid cache file
33263365
end
33273366
modules, (includes, _, requires), required_modules, srctextpos, prefs, prefs_hash, clone_targets, flags = parse_cache_header(io, cachefile)
33283367
if isempty(modules)
3368+
isnothing(reasons) || (reasons.empty_file += 1)
33293369
return true # ignore empty file
33303370
end
33313371
if ccall(:jl_match_cache_flags, UInt8, (UInt8,), flags) == 0
@@ -3334,6 +3374,7 @@ end
33343374
current session: $(CacheFlags())
33353375
cache file: $(CacheFlags(flags))
33363376
"""
3377+
isnothing(reasons) || (reasons.mismatched_flags += 1)
33373378
return true
33383379
end
33393380
pkgimage = !isempty(clone_targets)
@@ -3342,6 +3383,7 @@ end
33423383
if JLOptions().use_pkgimages == 0
33433384
# presence of clone_targets means native code cache
33443385
@debug "Rejecting cache file $cachefile for $modkey since it would require usage of pkgimage"
3386+
isnothing(reasons) || (reasons.requires_pkgimages += 1)
33453387
return true
33463388
end
33473389
rejection_reasons = check_clone_targets(clone_targets)
@@ -3350,10 +3392,12 @@ end
33503392
Reasons=rejection_reasons,
33513393
var"Image Targets"=parse_image_targets(clone_targets),
33523394
var"Current Targets"=current_image_targets())
3395+
isnothing(reasons) || (reasons.target_mismatch += 1)
33533396
return true
33543397
end
33553398
if !isfile(ocachefile)
33563399
@debug "Rejecting cache file $cachefile for $modkey since pkgimage $ocachefile was not found"
3400+
isnothing(reasons) || (reasons.missing_ocachefile += 1)
33573401
return true
33583402
end
33593403
else
@@ -3362,12 +3406,14 @@ end
33623406
id = first(modules)
33633407
if id.first != modkey && modkey != PkgId("")
33643408
@debug "Rejecting cache file $cachefile for $modkey since it is for $id instead"
3409+
isnothing(reasons) || (reasons.for_different_id += 1)
33653410
return true
33663411
end
33673412
if build_id != UInt128(0)
33683413
id_build = (UInt128(checksum) << 64) | id.second
33693414
if id_build != build_id
33703415
@debug "Ignoring cache file $cachefile for $modkey ($((UUID(id_build)))) since it does not provide desired build_id ($((UUID(build_id))))"
3416+
isnothing(reasons) || (reasons.for_different_buildid += 1)
33713417
return true
33723418
end
33733419
end
@@ -3389,13 +3435,15 @@ end
33893435
@goto locate_branch
33903436
else
33913437
@debug "Rejecting cache file $cachefile because module $req_key is already loaded and incompatible."
3438+
isnothing(reasons) || (reasons.loaded_incompatible += 1)
33923439
return true # Won't be able to fulfill dependency
33933440
end
33943441
else
33953442
@label locate_branch
33963443
path = locate_package(req_key)
33973444
if path === nothing
33983445
@debug "Rejecting cache file $cachefile because dependency $req_key not found."
3446+
isnothing(reasons) || (reasons.missing_source += 1)
33993447
return true # Won't be able to fulfill dependency
34003448
end
34013449
depmods[i] = (path, req_key, req_build_id)
@@ -3415,6 +3463,7 @@ end
34153463
break
34163464
end
34173465
@debug "Rejecting cache file $cachefile because it provides the wrong build_id (got $((UUID(build_id)))) for $req_key (want $(UUID(req_build_id)))"
3466+
isnothing(reasons) || (reasons.wrong_buildid += 1)
34183467
return true # cachefile doesn't provide the required version of the dependency
34193468
end
34203469
end
@@ -3423,27 +3472,31 @@ end
34233472
if !skip_check
34243473
if !samefile(includes[1].filename, modpath) && !samefile(fixup_stdlib_path(includes[1].filename), modpath)
34253474
@debug "Rejecting cache file $cachefile because it is for file $(includes[1].filename) not file $modpath"
3475+
isnothing(reasons) || (reasons.different_source += 1)
34263476
return true # cache file was compiled from a different path
34273477
end
34283478
for (modkey, req_modkey) in requires
34293479
# verify that `require(modkey, name(req_modkey))` ==> `req_modkey`
34303480
pkg = identify_package(modkey, req_modkey.name)
34313481
if pkg != req_modkey
34323482
@debug "Rejecting cache file $cachefile because uuid mapping for $modkey => $req_modkey has changed, expected $modkey => $pkg"
3483+
isnothing(reasons) || (reasons.uuid_change += 1)
34333484
return true
34343485
end
34353486
end
34363487
for chi in includes
34373488
f, fsize_req, hash_req, ftime_req = chi.filename, chi.fsize, chi.hash, chi.mtime
34383489
if startswith(f, "@depot/")
34393490
@debug("Rejecting stale cache file $cachefile because its depot could not be resolved")
3491+
isnothing(reasons) || (reasons.unresolvable_depot += 1)
34403492
return true
34413493
end
34423494
if !ispath(f)
34433495
_f = fixup_stdlib_path(f)
34443496
if isfile(_f) && startswith(_f, Sys.STDLIB)
34453497
continue
34463498
end
3499+
isnothing(reasons) || (reasons.missing_sourcefile += 1)
34473500
@debug "Rejecting stale cache file $cachefile because file $f does not exist"
34483501
return true
34493502
end
@@ -3458,17 +3511,20 @@ end
34583511
!( 0 < (ftime_req - ftime) < 1e-6 ) # PR #45552: Compensate for Windows tar giving mtimes that may be incorrect by up to one microsecond
34593512
if is_stale
34603513
@debug "Rejecting stale cache file $cachefile because mtime of include_dependency $f has changed (mtime $ftime, before $ftime_req)"
3514+
isnothing(reasons) || (reasons.include_dependency_mtime_change += 1)
34613515
return true
34623516
end
34633517
else
34643518
fsize = filesize(f)
34653519
if fsize != fsize_req
34663520
@debug "Rejecting stale cache file $cachefile because file size of $f has changed (file size $fsize, before $fsize_req)"
3521+
isnothing(reasons) || (reasons.include_dependency_fsize_change += 1)
34673522
return true
34683523
end
34693524
hash = open(_crc32c, f, "r")
34703525
if hash != hash_req
34713526
@debug "Rejecting stale cache file $cachefile because hash of $f has changed (hash $hash, before $hash_req)"
3527+
isnothing(reasons) || (reasons.include_dependency_fhash_change += 1)
34723528
return true
34733529
end
34743530
end
@@ -3477,19 +3533,22 @@ end
34773533

34783534
if !isvalid_file_crc(io)
34793535
@debug "Rejecting cache file $cachefile because it has an invalid checksum"
3536+
isnothing(reasons) || (reasons.invalid_checksum += 1)
34803537
return true
34813538
end
34823539

34833540
if pkgimage
34843541
if !isvalid_pkgimage_crc(io, ocachefile::String)
34853542
@debug "Rejecting cache file $cachefile because $ocachefile has an invalid checksum"
3543+
isnothing(reasons) || (reasons.ocachefile_invalid_checksum += 1)
34863544
return true
34873545
end
34883546
end
34893547

34903548
curr_prefs_hash = get_preferences_hash(id.uuid, prefs)
34913549
if prefs_hash != curr_prefs_hash
34923550
@debug "Rejecting cache file $cachefile because preferences hash does not match 0x$(string(prefs_hash, base=16)) != 0x$(string(curr_prefs_hash, base=16))"
3551+
isnothing(reasons) || (reasons.prefs_hash_mismatch += 1)
34933552
return true
34943553
end
34953554

0 commit comments

Comments
 (0)