loading: add JULIA_PRECOMPILE_CACHE_KEY to cache file names - #63294
IanButterworth wants to merge 1 commit into
Conversation
How would this work on an HPC cluster with multiple head nodes and multiple compute nodes, but a single filesystem mounted across all nodes? |
|
The first one to precompile it would give it a name based on those keys, then the others would use it. The filename doesn't restrict cache usage. |
|
I guess a worry with this is that the hostname could be too volatile especially on laptops as it can be dependent on network characteristics, which would make a single project use up more cache slots. |
8f1ca12 to
b6156a9
Compare
JULIA_PRECOMPILE_CACHE_KEY to cache file namesJULIA_PRECOMPILE_CACHE_KEY to cache file names
Cache file names are keyed on the active project path, so containers that share a depot but mount different projects at the same path (say `/work`) give incompatible caches the same name and overwrite each other: alternating loads recompile every time and concurrent precompilation fails with "Required dependency ... failed to load from a cache file" or "Module ... is missing from the cache" when a file is replaced between the staleness check and the load. Mix the value of `JULIA_PRECOMPILE_CACHE_KEY` into the name when it is set, on top of the existing project path, preferences, flags and binary inputs rather than in place of any of them, so a runner can give each app a stable, distinct key. Loading reads file contents rather than names, so a compatible cache written under one key is still reused under another, and a changed key only takes another file when a compile actually happens. The pidfile path leaves the key out, so locking stays shared. Apps with the same key and project path collide as before. Fixes JuliaLang#63268 Assisted-by: Claude Code (Opus 5)
b6156a9 to
282e752
Compare
|
@KristofferC I'm not sure if there's a cleaner fix we can backport without adding an env var, perhaps this is acceptable? |
| If set, an extra string mixed into the name of precompile cache files, on top of what | ||
| already distinguishes them (the project path, the preferences, the compiler flags and the | ||
| julia binary). It does not replace any of those. The name only decides which existing | ||
| file a compile overwrites; loading checks file contents, so a cache written under one | ||
| value is still reused under another. Setting a stable, distinct value per app lets | ||
| containers that share a depot but mount different projects at the same path (say `/work`) | ||
| keep their caches from overwriting each other. Apps with the same key and project path | ||
| still collide. |
There was a problem hiding this comment.
This feels like it should be rewritten by a human. It currently seems to assume you are a robot who has read exactly how loading.jl is implemented.
There was a problem hiding this comment.
Happy to polish this if the approach sounds ok?
There was a problem hiding this comment.
The approach seems a bit bad, but I'm not sure what else you'd do. It doesn't hurt anything, just an extra 200 lines of code (mostly tests)
There was a problem hiding this comment.
I think these might be a better approach #63310 JuliaLang/Pkg.jl#4824
Fixes #63268
Claude:
Narrow alternative to #63293. Cache file names are keyed on the active project path, so containers that share a depot but mount different projects at the same path (say
/work) give incompatible caches the same name and overwrite each other: alternating loads recompile every time, and concurrent precompilation fails with "Required dependency ... failed to load from a cache file" or "Module ... is missing from the cache".Change
JULIA_PRECOMPILE_CACHE_KEY: if set, its value is mixed into the cache file name on top of the existing inputs (project path, preferences, flags, cpu target, julia binary and sysimage). It adds uniqueness; it does not replace any of them. The LRU and cleanup are untouched. Documented in the manual.What it does and does not do
Tests
In
test/precompile.jl, using the key to stand in for separate apps: incompatible versions at one project path written under different keys coexist with their dependents and are reused when alternating (fails on nightly: the second write overwrites the first); a compatible cache is reused under another key without a new file; a rebuild under the same key and project replaces the same file; projects with different preferences keep separate files; unset/empty/set semantics and pidfile independence.precompileandloadingtest files pass locally. The two-container case itself was not run; it needs Linux mount namespaces.