@@ -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)
25692569for 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 )
25762576end
25772577
25782578const MAX_NUM_PRECOMPILE_FILES = Ref (10 )
25792579
25802580function 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
33133313end
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)
33183328end
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