feat: add Lean.CompactedRegion.save/read supporting cross-file object sharing#13185
Conversation
|
!bench |
|
Benchmark results for 510303f against 4786e08 are in. Significant changes detected! @Kha
Large changes (5🟥)
Small changes (51🟥) Too many entries to display here. View the full report on radar instead. |
|
Reference manual CI status:
|
|
Mathlib CI status (docs):
|
|
!bench |
|
Benchmark results for 0f23528 against 4786e08 are in. There are no significant changes. @Kha
Small changes (2🟥)
|
|
Mathlib CI status (docs):
|
|
Mathlib CI status (docs):
|
|
Mathlib CI status (docs):
|
|
Mathlib CI status (docs):
|
|
Mathlib CI status (docs):
|
17a86da to
d14a467
Compare
|
!bench |
|
Benchmark results for d14a467 against 8c82f9e are in. There are significant results. @Kha
Large changes (1🟥)
Small changes (2✅, 3🟥)
|
|
!bench |
|
Benchmark results for 95e7047 against 8c82f9e are in. There are significant results. @Kha
Large changes (1🟥)
Small changes (1✅, 3🟥)
|
saveModuleDataIncr/readModuleDataIncr with dep region sharingLean.CompactedRegion.save/read supporting cross-file object sharing
This PR adds `Lean.CompactedRegion.save` and `Lean.CompactedRegion.read` as the primary low-level olean save/load primitives, generic in the serialized data type. The existing `ModuleData`-typed functions (`saveModuleData`/`readModuleData` and the `*Parts` variants) become thin wrappers around them. Two sharing mechanisms are supported: * `CompactedRegion` dep regions: objects already present in a loaded dep region are emitted as cross-region pointers rather than re-serialized, and the loader's `fix_object_ptr` resolves them via a binary search over deps sorted by saved `base_addr`. * A `Compactor` chaining handle: consecutive saves with the same `Compactor` reuse the prior call's pointer-identity and structural-sharing tables so objects shared across parts are emitted exactly once. The reader maps oleans `MAP_PRIVATE | PROT_READ | PROT_WRITE` so the pointer-fixup walk can write the loaded buffer in place when needed (`MAP_PRIVATE` keeps unwritten pages shared with the page cache, so the write protection is free when no fixup happens). On Linux, `MAP_FIXED_NOREPLACE` is OR'd in when available (with a `#define` fallback for older glibc) to let the kernel atomically reject collisions at the saved `base_addr`; macOS doesn't expose the flag, and the post-check + cleanup `munmap` handles the same case there. The fast path in `compacted_region::read()` skips the full object walk when both the region itself and every dep region landed at their saved addresses; otherwise it falls through to the full fix-up walk. The `compacted_region` constructor rejects overlapping saved `base_addr` ranges to avoid silent translation through the wrong region.
… tests `tests/compile/run_bench.sh` only emitted `<test>.measurements.jsonl` from the `if [[ -n $DO_COMPILE ]]` block, and the earlier `rm -f` removed any stale file. With `.no_compile` set, the file never existed, and `combine.py` later crashed with `FileNotFoundError` when reading the expected per-test jsonl. Truncate-or-create the file unconditionally before the block so an empty measurements file is always available.
8100976 to
e609d91
Compare
| fi | ||
|
|
||
| rm -f "$1.measurements.jsonl" | ||
| : > "$1.measurements.jsonl" # always create (possibly empty) so `combine.py` finds it |
There was a problem hiding this comment.
FYI @Garmelon; not sure using .no_compile in compile/ really is the best approach, could be a new pile run/ instead?
This PR adds new incremental module serialization functions that save/load a single module at a time with explicit sharing via dep regions and compactor state, generalizing the existing batch saveModuleDataParts API.
Two sharing mechanisms that can be mixed:
CompactedRegiondep regions for sharing with loaded regionsCompactorStatefor same-process chaining (pre-loadedm_obj_table)