Skip to content

Commit 26d0460

Browse files
Show more info on why package precompilation was needed (#52619)
1 parent e6e572e commit 26d0460

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

base/loading.jl

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,11 +1633,11 @@ end
16331633

16341634
# returns `nothing` if require found a precompile cache for this sourcepath, but couldn't load it
16351635
# 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)
1636+
@constprop :none function _require_search_from_serialized(pkg::PkgId, sourcepath::String, build_id::UInt128; reasons=nothing)
16371637
assert_havelock(require_lock)
16381638
paths = find_all_in_cache_path(pkg)
16391639
for path_to_try in paths::Vector{String}
1640-
staledeps = stale_cachefile(pkg, build_id, sourcepath, path_to_try)
1640+
staledeps = stale_cachefile(pkg, build_id, sourcepath, path_to_try; reasons)
16411641
if staledeps === true
16421642
continue
16431643
end
@@ -2126,11 +2126,11 @@ function _require(pkg::PkgId, env=nothing)
21262126
set_pkgorigin_version_path(pkg, path)
21272127

21282128
pkg_precompile_attempted = false # being safe to avoid getting stuck in a Pkg.precompile loop
2129-
2129+
reasons = Dict{String,Int}()
21302130
# attempt to load the module file via the precompile cache locations
21312131
if JLOptions().use_compiled_modules != 0
21322132
@label load_from_cache
2133-
m = _require_search_from_serialized(pkg, path, UInt128(0))
2133+
m = _require_search_from_serialized(pkg, path, UInt128(0); reasons)
21342134
if m isa Module
21352135
return m
21362136
end
@@ -2166,7 +2166,7 @@ function _require(pkg::PkgId, env=nothing)
21662166
# double-check now that we have lock
21672167
m = _require_search_from_serialized(pkg, path, UInt128(0))
21682168
m isa Module && return m
2169-
compilecache(pkg, path)
2169+
compilecache(pkg, path; reasons)
21702170
end
21712171
cachefile_or_module isa Module && return cachefile_or_module::Module
21722172
cachefile = cachefile_or_module
@@ -2568,17 +2568,17 @@ This can be used to reduce package load times. Cache files are stored in
25682568
`DEPOT_PATH[1]/compiled`. See [Module initialization and precompilation](@ref)
25692569
for important notes.
25702570
"""
2571-
function compilecache(pkg::PkgId, internal_stderr::IO = stderr, internal_stdout::IO = stdout)
2571+
function compilecache(pkg::PkgId, internal_stderr::IO = stderr, internal_stdout::IO = stdout; reasons::Union{Dict{String,Int},Nothing}=nothing)
25722572
@nospecialize internal_stderr internal_stdout
25732573
path = locate_package(pkg)
25742574
path === nothing && throw(ArgumentError("$pkg not found during precompilation"))
2575-
return compilecache(pkg, path, internal_stderr, internal_stdout)
2575+
return compilecache(pkg, path, internal_stderr, internal_stdout; reasons)
25762576
end
25772577

25782578
const MAX_NUM_PRECOMPILE_FILES = Ref(10)
25792579

25802580
function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, internal_stdout::IO = stdout,
2581-
keep_loaded_modules::Bool = true)
2581+
keep_loaded_modules::Bool = true; reasons::Union{Dict{String,Int},Nothing}=nothing)
25822582

25832583
@nospecialize internal_stderr internal_stdout
25842584
# decide where to put the resulting cache file
@@ -2595,7 +2595,7 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in
25952595
end
25962596
# run the expression and cache the result
25972597
verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug
2598-
@logmsg verbosity "Precompiling $pkg"
2598+
@logmsg verbosity "Precompiling $pkg $(list_reasons(reasons))"
25992599

26002600
# create a temporary file in `cachepath` directory, write the cache in it,
26012601
# write the checksum, _and then_ atomically move the file to `cachefile`.
@@ -3311,17 +3311,29 @@ function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String; stale_age=compilec
33113311
f()
33123312
end
33133313
end
3314+
3315+
function record_reason(reasons::Dict{String,Int}, reason::String)
3316+
reasons[reason] = get(reasons, reason, 0) + 1
3317+
end
3318+
record_reason(::Nothing, ::String) = nothing
3319+
function list_reasons(reasons::Dict{String,Int})
3320+
isempty(reasons) && return ""
3321+
return "(cache misses: $(join(("$k ($v)" for (k,v) in reasons), ", ")))"
3322+
end
3323+
33143324
# returns true if it "cachefile.ji" is stale relative to "modpath.jl" and build_id for modkey
33153325
# otherwise returns the list of dependencies to also check
3316-
@constprop :none function stale_cachefile(modpath::String, cachefile::String; ignore_loaded::Bool = false)
3326+
@constprop :none function stale_cachefile(modpath::String, cachefile::String; ignore_loaded::Bool = false, reasons=nothing)
33173327
return stale_cachefile(PkgId(""), UInt128(0), modpath, cachefile; ignore_loaded)
33183328
end
3319-
@constprop :none function stale_cachefile(modkey::PkgId, build_id::UInt128, modpath::String, cachefile::String; ignore_loaded::Bool = false)
3329+
@constprop :none function stale_cachefile(modkey::PkgId, build_id::UInt128, modpath::String, cachefile::String;
3330+
ignore_loaded::Bool = false, reasons::Union{Dict{String,Int},Nothing}=nothing)
33203331
io = open(cachefile, "r")
33213332
try
33223333
checksum = isvalid_cache_header(io)
33233334
if iszero(checksum)
33243335
@debug "Rejecting cache file $cachefile due to it containing an invalid cache header"
3336+
record_reason(reasons, "invalid header")
33253337
return true # invalid cache file
33263338
end
33273339
modules, (includes, _, requires), required_modules, srctextpos, prefs, prefs_hash, clone_targets, flags = parse_cache_header(io, cachefile)
@@ -3334,6 +3346,7 @@ end
33343346
current session: $(CacheFlags())
33353347
cache file: $(CacheFlags(flags))
33363348
"""
3349+
record_reason(reasons, "mismatched flags")
33373350
return true
33383351
end
33393352
pkgimage = !isempty(clone_targets)
@@ -3342,6 +3355,7 @@ end
33423355
if JLOptions().use_pkgimages == 0
33433356
# presence of clone_targets means native code cache
33443357
@debug "Rejecting cache file $cachefile for $modkey since it would require usage of pkgimage"
3358+
record_reason(reasons, "requires pkgimages")
33453359
return true
33463360
end
33473361
rejection_reasons = check_clone_targets(clone_targets)
@@ -3350,10 +3364,12 @@ end
33503364
Reasons=rejection_reasons,
33513365
var"Image Targets"=parse_image_targets(clone_targets),
33523366
var"Current Targets"=current_image_targets())
3367+
record_reason(reasons, "target mismatch")
33533368
return true
33543369
end
33553370
if !isfile(ocachefile)
33563371
@debug "Rejecting cache file $cachefile for $modkey since pkgimage $ocachefile was not found"
3372+
record_reason(reasons, "missing ocachefile")
33573373
return true
33583374
end
33593375
else
@@ -3362,12 +3378,14 @@ end
33623378
id = first(modules)
33633379
if id.first != modkey && modkey != PkgId("")
33643380
@debug "Rejecting cache file $cachefile for $modkey since it is for $id instead"
3381+
record_reason(reasons, "for different pkgid")
33653382
return true
33663383
end
33673384
if build_id != UInt128(0)
33683385
id_build = (UInt128(checksum) << 64) | id.second
33693386
if id_build != build_id
33703387
@debug "Ignoring cache file $cachefile for $modkey ($((UUID(id_build)))) since it does not provide desired build_id ($((UUID(build_id))))"
3388+
record_reason(reasons, "for different buildid")
33713389
return true
33723390
end
33733391
end
@@ -3389,13 +3407,15 @@ end
33893407
@goto locate_branch
33903408
else
33913409
@debug "Rejecting cache file $cachefile because module $req_key is already loaded and incompatible."
3410+
record_reason(reasons, req_key == PkgId(Core) ? "wrong julia version" : "wrong dep version loaded")
33923411
return true # Won't be able to fulfill dependency
33933412
end
33943413
else
33953414
@label locate_branch
33963415
path = locate_package(req_key)
33973416
if path === nothing
33983417
@debug "Rejecting cache file $cachefile because dependency $req_key not found."
3418+
record_reason(reasons, "dep missing source")
33993419
return true # Won't be able to fulfill dependency
34003420
end
34013421
depmods[i] = (path, req_key, req_build_id)
@@ -3415,6 +3435,7 @@ end
34153435
break
34163436
end
34173437
@debug "Rejecting cache file $cachefile because it provides the wrong build_id (got $((UUID(build_id)))) for $req_key (want $(UUID(req_build_id)))"
3438+
record_reason(reasons, "wrong dep buildid")
34183439
return true # cachefile doesn't provide the required version of the dependency
34193440
end
34203441
end
@@ -3423,20 +3444,23 @@ end
34233444
if !skip_check
34243445
if !samefile(includes[1].filename, modpath) && !samefile(fixup_stdlib_path(includes[1].filename), modpath)
34253446
@debug "Rejecting cache file $cachefile because it is for file $(includes[1].filename) not file $modpath"
3447+
record_reason(reasons, "wrong source")
34263448
return true # cache file was compiled from a different path
34273449
end
34283450
for (modkey, req_modkey) in requires
34293451
# verify that `require(modkey, name(req_modkey))` ==> `req_modkey`
34303452
pkg = identify_package(modkey, req_modkey.name)
34313453
if pkg != req_modkey
34323454
@debug "Rejecting cache file $cachefile because uuid mapping for $modkey => $req_modkey has changed, expected $modkey => $pkg"
3455+
record_reason(reasons, "dep uuid changed")
34333456
return true
34343457
end
34353458
end
34363459
for chi in includes
34373460
f, fsize_req, hash_req, ftime_req = chi.filename, chi.fsize, chi.hash, chi.mtime
34383461
if startswith(f, "@depot/")
34393462
@debug("Rejecting stale cache file $cachefile because its depot could not be resolved")
3463+
record_reason(reasons, "nonresolveable depot")
34403464
return true
34413465
end
34423466
if !ispath(f)
@@ -3445,6 +3469,7 @@ end
34453469
continue
34463470
end
34473471
@debug "Rejecting stale cache file $cachefile because file $f does not exist"
3472+
record_reason(reasons, "missing sourcefile")
34483473
return true
34493474
end
34503475
if ftime_req >= 0.0
@@ -3458,17 +3483,20 @@ end
34583483
!( 0 < (ftime_req - ftime) < 1e-6 ) # PR #45552: Compensate for Windows tar giving mtimes that may be incorrect by up to one microsecond
34593484
if is_stale
34603485
@debug "Rejecting stale cache file $cachefile because mtime of include_dependency $f has changed (mtime $ftime, before $ftime_req)"
3486+
record_reason(reasons, "include_dependency mtime change")
34613487
return true
34623488
end
34633489
else
34643490
fsize = filesize(f)
34653491
if fsize != fsize_req
34663492
@debug "Rejecting stale cache file $cachefile because file size of $f has changed (file size $fsize, before $fsize_req)"
3493+
record_reason(reasons, "include_dependency fsize change")
34673494
return true
34683495
end
34693496
hash = open(_crc32c, f, "r")
34703497
if hash != hash_req
34713498
@debug "Rejecting stale cache file $cachefile because hash of $f has changed (hash $hash, before $hash_req)"
3499+
record_reason(reasons, "include_dependency fhash change")
34723500
return true
34733501
end
34743502
end
@@ -3477,19 +3505,22 @@ end
34773505

34783506
if !isvalid_file_crc(io)
34793507
@debug "Rejecting cache file $cachefile because it has an invalid checksum"
3508+
record_reason(reasons, "invalid checksum")
34803509
return true
34813510
end
34823511

34833512
if pkgimage
34843513
if !isvalid_pkgimage_crc(io, ocachefile::String)
34853514
@debug "Rejecting cache file $cachefile because $ocachefile has an invalid checksum"
3515+
record_reason(reasons, "ocachefile invalid checksum")
34863516
return true
34873517
end
34883518
end
34893519

34903520
curr_prefs_hash = get_preferences_hash(id.uuid, prefs)
34913521
if prefs_hash != curr_prefs_hash
34923522
@debug "Rejecting cache file $cachefile because preferences hash does not match 0x$(string(prefs_hash, base=16)) != 0x$(string(curr_prefs_hash, base=16))"
3523+
record_reason(reasons, "preferences hash mismatch")
34933524
return true
34943525
end
34953526

0 commit comments

Comments
 (0)