Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

perf: lazy IR loading#14145

Draft
Kha wants to merge 10 commits into
master from
lazy-ir-loading
Draft

perf: lazy IR loading #14145
Kha wants to merge 10 commits into
master from
lazy-ir-loading

Conversation

@Kha

@Kha Kha commented Jun 22, 2026

Copy link
Copy Markdown
Member

No description provided.

Kha and others added 3 commits June 22, 2026 09:24
This PR threads `BaseIO` through `getModuleIREntries` and the interpreter/codegen lookups that consume imported IR, in preparation for loading imported IR on demand. There is no behavior change yet: the lookups still read the eagerly-imported state.
`getModuleIREntries`, `findInterpDecl`/`findInterpDeclBoxed`, `findEnvDecl`/`findEnvDecl'`, `getSorryDep`, and `getRegularInitAttrModIdxs` become `BaseIO`; `findExtEntry?` is split so the non-IR LCNF lookups stay pure and a new `findIRExtEntry?` carries the IR branch. The C-export ABI is unchanged: `BaseIO` compiles to a bare value-return (no world argument, no error wrapper), so `ir_interpreter.cpp` needs no changes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This PR makes `[inherit_doc]` copy the resolved docstring when a public declaration inherits one from a private declaration, instead of storing an alias to the private name. An importer cannot resolve such an alias because the private target is not exported and has no module index, so the inherited docstring would be lost across modules. Since the source is available where the attribute is applied, its docstring is copied eagerly; all other cases keep the existing alias behavior.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This PR loads a module's interpreter IR (`.ir`) lazily, on first use, instead of eagerly populating the IR extension state for every imported module at import time. Modules whose interpreter IR is already part of the imported `.olean` data are read as before; module-system modules with a separate `.ir` are memory-mapped and cached on first access.
`Kernel.Environment`'s `irBaseExts : Array EnvExtensionState` field becomes `irData : Option LazyIR`, holding the per-module `.ir` paths and a mutable `IO.Ref` cache populated via `modifyGet`. `getModuleIREntries` becomes `BaseIO`; the C-export ABI is unchanged because `BaseIO` compiles to a bare value return. A lazy index maps code-generator auxiliary constants discovered while loading `.ir` files, consulted by the interpreter and codegen lookups when `getModuleIdxFor?` misses. `const2ModIdx` auxiliaries are sourced from the already-loaded `.olean` data.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Kha commented Jun 22, 2026

Copy link
Copy Markdown
Member Author

!bench

leanprover-radar commented Jun 22, 2026
edited
Loading

Copy link
Copy Markdown

Benchmark results for ecebaec against bc5f89f are in. There are significant results. @Kha

  • 🟥 build//instructions: +128.3G (+1.13%)

Large changes (25✅, 30🟥)

Too many entries to display here. View the full report on radar instead.

Medium changes (2✅, 25🟥)

Too many entries to display here. View the full report on radar instead.

Small changes (21✅, 1880🟥)

Too many entries to display here. View the full report on radar instead.

@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Jun 22, 2026

leanprover-bot commented Jun 22, 2026
edited
Loading

Copy link
Copy Markdown
Collaborator

Reference manual CI status:

  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2026年06月19日 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2026年06月22日 14:57:21)
  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2026年06月23日 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2026年06月23日 11:26:30)

@github-actions github-actions Bot added the mathlib4-nightly-available A branch for this PR exists at leanprover-community/mathlib4-nightly-testing:lean-pr-testing-NNNN label Jun 22, 2026
@mathlib-lean-pr-testing mathlib-lean-pr-testing Bot added the breaks-mathlib This is not necessarily a blocker for merging: but there needs to be a plan label Jun 22, 2026

mathlib-lean-pr-testing Bot commented Jun 22, 2026
edited
Loading

Copy link
Copy Markdown

Mathlib CI status (docs):

Copy link
Copy Markdown
Contributor

!bench

leanprover-radar commented Jun 22, 2026
edited
Loading

Copy link
Copy Markdown

Benchmark results for 46ccc24 against bc5f89f are in. There are significant results. @hargoniX

  • 🟥 build//instructions: +53.0G (+0.47%)

Large changes (26✅, 5🟥)

Too many entries to display here. View the full report on radar instead.

Medium changes (2✅, 17🟥)

  • compiled/incr_header_load//instructions: -107.0M (-17.20%)
  • 🟥 elab/big_beq//instructions: +116.2M (+1.33%)
  • 🟥 elab/big_deceq//instructions: +113.7M (+2.78%)
  • 🟥 elab/big_deceq_rec//instructions: +113.9M (+2.06%)
  • 🟥 elab/big_match//instructions: +110.0M (+1.07%)
  • 🟥 elab/big_match_nat//instructions: +100.9M (+2.19%)
  • 🟥 elab/big_match_partial//instructions: +126.9M (+0.92%)
  • 🟥 elab/cbv_dedup//instructions: +50.4M (+1.59%)
  • elab/cbv_leroy//maxrss: -125MiB (-6.78%)
  • 🟥 elab/delayed_assign//instructions: +110.7M (+3.41%)
  • 🟥 elab/delayed_sharing//instructions: +117.0M (+4.57%)
  • 🟥 elab/iterators//instructions: +44.5M (+1.81%)
  • 🟥 elab/simp_arith1//instructions: +88.9M (+4.12%)
  • 🟥 elab/string_simp_ne//instructions: +101.1M (+1.84%)
  • 🟥 interpreted/iterators//instructions: +47.8M (+0.13%)
  • 🟥 lake/inundation/config elab//instructions: +37.5M (+1.71%)
  • 🟥 lake/inundation/config import//instructions: +32.6M (+2.92%)
  • 🟥 lake/inundation/config tree//instructions: +33.9M (+2.95%)
  • 🟥 lake/inundation/env//instructions: +31.5M (+2.78%)

Small changes (44✅, 1440🟥)

Too many entries to display here. View the full report on radar instead.

mathlib-nightly-testing Bot pushed a commit to leanprover-community/batteries that referenced this pull request Jun 22, 2026
mathlib-nightly-testing Bot pushed a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Jun 22, 2026
mathlib-nightly-testing Bot pushed a commit to leanprover-community/batteries that referenced this pull request Jun 22, 2026
mathlib-nightly-testing Bot pushed a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Jun 22, 2026

Kha commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

!bench

leanprover-radar commented Jun 23, 2026
edited
Loading

Copy link
Copy Markdown

Benchmark results for 1706713 against ab97228 are in. There are significant results. @Kha

  • 🟥 build//instructions: +14.0G (+0.12%)

New metrics (6✅, 29🟥, 13)

Too many entries to display here. View the full report on radar instead.

Large changes (5✅, 1🟥)

  • 🟥 build/profile/compilation (IR)//wall-clock: +5s (+88.43%)
  • build/stat/imported bytes//bytes: -2GiB (-14.69%)
  • build/stat/imported modules//amount: -662.9k (-38.74%)
  • elab/charactersIn//maxrss: -79MiB (-9.68%)
  • elab/workspaceSymbols//maxrss: -84MiB (-10.44%)
  • misc/import Lean//maxrss: -45MiB (-8.84%)

Medium changes (1✅)

  • compiled/incr_header_save//maxrss: -8MiB (-0.40%)

Small changes (95✅, 339🟥)

Too many entries to display here. View the full report on radar instead.

mathlib-nightly-testing Bot pushed a commit to leanprover-community/batteries that referenced this pull request Jun 23, 2026
mathlib-nightly-testing Bot pushed a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Jun 23, 2026
Kha and others added 2 commits June 23, 2026 15:48
Reconcile the lazy interpreter-IR loading work with master's multi-part IR refactor (`irParts` = `.ir.sig` + `.ir`).
Master split a module's interpreter IR into chained compacted regions (the `.ir` is compacted relative to the `.ir.sig` region), while this branch made that IR load lazily. The two are reconciled with a per-module `Kernel.IRSource` (`loaded` / `deferred` / `absent`):
* `deferred` modules store their IR part paths and load them on demand via `readModuleDataParts` (the same region chaining as the eager path), caching the full `.ir` and keeping every part region alive. Reading the `.ir` on its own left its cross-region pointers into the `.ir.sig` region dangling, segfaulting the interpreter on first use.
* The lazy cache `IO.Ref` is swapped for a fresh, non-persistent one after each `markPersistent` (in both `base.private` and `checked`), mirroring `realizeMapRef`, so the persistent environment never freezes a mutable cell.
* Eagerly-loaded (`import all`, IR-only, leanir) modules source their `const2ModIdx` code-generator auxiliaries from the `.ir` (the full set, including private ones, as before the lazy change); deferred modules register theirs in `extraIdx` when their `.ir` is loaded on demand.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
...table
This PR lets the interpreter load a module's IR on demand even when it references code-generator auxiliaries or private symbols defined in another module, by recording in each `.ir` the defining module of every such symbol its code references.
When the interpreter runs an imported module's IR and calls a symbol that is not a kernel constant (a specialization, a private initializer, a boxed wrapper), `const2ModIdx` cannot locate it and the defining module may never have been loaded, so the lookup fails with `(interpreter) unknown declaration`. Each `.ir` now ships a referenced-symbol → defining-module side table, computed at code-generation time when `const2ModIdx` is complete; loading a `.ir` merges it into the on-demand index, so the referenced module's `.ir` is loaded when the symbol is first called. Only the interpreter needs this: code generation, the IR checker, and `getSorryDep` only reference kernel constants or current-module declarations, which are already in `const2ModIdx`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Kha Kha force-pushed the lazy-ir-loading branch from 1706713 to 7415e9a Compare June 23, 2026 19:26

Kha commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

!bench

leanprover-radar commented Jun 23, 2026
edited
Loading

Copy link
Copy Markdown

Benchmark results for 7415e9a against ab97228 are in. There are significant results. @Kha

  • 🟥 build//instructions: +18.2G (+0.16%)

New metrics (11✅, 15🟥, 12)

Too many entries to display here. View the full report on radar instead.

Large changes (5✅, 1🟥)

  • 🟥 build/profile/compilation (IR)//wall-clock: +5s (+90.61%)
  • build/stat/imported bytes//bytes: -2GiB (-14.67%)
  • build/stat/imported modules//amount: -662.9k (-38.74%)
  • elab/charactersIn//maxrss: -75MiB (-9.19%)
  • elab/workspaceSymbols//maxrss: -84MiB (-10.40%)
  • misc/import Lean//maxrss: -43MiB (-8.56%)

Medium changes (1✅, 1🟥)

  • elab/big_deceq_rec//maxrss: -13MiB (-0.73%)
  • 🟥 size/all/.ir//bytes: +2MiB (+0.46%)

Small changes (77✅, 418🟥)

Too many entries to display here. View the full report on radar instead.

mathlib-nightly-testing Bot pushed a commit to leanprover-community/batteries that referenced this pull request Jun 23, 2026
mathlib-nightly-testing Bot pushed a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Jun 23, 2026
...declaration lookup
This PR removes the `lazyIRModuleIdxFor?` fallback from `findIRExtEntry?`, the lookup behind code generation's `findEnvDecl`. Code generation only references kernel constants (which are in `const2ModIdx`) and current-module declarations, so it never reaches the on-demand auxiliary index; only the interpreter does, and it keeps its own fallback.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This PR removes the `ModuleData.extraConstNames` field and fills `const2ModIdx`'s code-generator auxiliaries at import time from each module's already-loaded `declMapExt` and `monoExt` entries instead, dropping a duplicated copy of those names from the olean.
For eagerly-loaded IR (`import all`, leanir, IR-only modules) the auxiliaries come from the full `.ir` `declMapExt`; for a deferred module they come from the `.olean`'s `declMapExt` (public IR and boxed externs) together with `monoExt`'s private specializations, which `monoExt` keeps in `.olean.private` so that inlineable bodies referencing them stay resolvable. Remaining private auxiliaries register in `extraIdx` when the module's `.ir` is loaded on demand. The extraction runs in the compiler layer via `extractIRConstNames` and `extractMonoConstNames` so `finalizeImport` need not see the IR declaration types.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Kha commented Jun 25, 2026

Copy link
Copy Markdown
Member Author

!bench

leanprover-radar commented Jun 25, 2026
edited
Loading

Copy link
Copy Markdown

Benchmark results for 5a89bd3 against ab97228 are in. There are significant results. @Kha

  • 🟥 build//instructions: +34.7G (+0.30%)

Large changes (3✅, 22🟥)

Too many entries to display here. View the full report on radar instead.

Medium changes (2✅, 15🟥)

  • 🟥 elab/big_deceq//instructions: +80.5M (+1.92%)
  • 🟥 elab/big_deceq//task-clock: +45ms (+9.22%)
  • 🟥 elab/big_deceq//wall-clock: +43ms (+8.31%)
  • 🟥 elab/big_deceq_rec//instructions: +73.4M (+1.30%)
  • 🟥 elab/big_match//instructions: +70.6M (+0.68%)
  • 🟥 elab/big_match_nat//instructions: +69.7M (+1.48%)
  • 🟥 elab/delayed_assign//instructions: +78.9M (+2.36%)
  • 🟥 elab/delayed_assign//task-clock: +41ms (+9.79%)
  • 🟥 elab/delayed_assign//wall-clock: +40ms (+9.68%)
  • 🟥 elab/delayed_sharing//instructions: +78.8M (+2.97%)
  • 🟥 elab/delayed_sharing//task-clock: +42ms (+11.87%)
  • 🟥 elab/delayed_sharing//wall-clock: +42ms (+11.32%)
  • 🟥 lake/inundation/config import//instructions: +41.2M (+3.57%)
  • 🟥 lake/inundation/config tree//instructions: +35.4M (+2.96%)
  • 🟥 lake/inundation/env//instructions: +36.7M (+3.12%)
  • size/all/.ir//bytes: -1MiB (-0.42%)
  • size/all/.olean.server//bytes: -161kiB (-0.52%)

Small changes (52✅, 1128🟥)

Too many entries to display here. View the full report on radar instead.

mathlib-nightly-testing Bot pushed a commit to leanprover-community/batteries that referenced this pull request Jun 25, 2026
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mathlib-nightly-testing Bot pushed a commit to leanprover-community/batteries that referenced this pull request Jun 25, 2026
mathlib-nightly-testing Bot pushed a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@digama0 digama0 Awaiting requested review from digama0 digama0 will be requested when the pull request is marked ready for review digama0 is a code owner
@leodemoura leodemoura Awaiting requested review from leodemoura leodemoura will be requested when the pull request is marked ready for review leodemoura is a code owner
@hargoniX hargoniX Awaiting requested review from hargoniX hargoniX will be requested when the pull request is marked ready for review hargoniX is a code owner

Assignees

No one assigned

Labels

breaks-mathlib This is not necessarily a blocker for merging: but there needs to be a plan mathlib4-nightly-available A branch for this PR exists at leanprover-community/mathlib4-nightly-testing:lean-pr-testing-NNNN toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /