perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

perf(ix): lazy, zero-copy anon env load for the Aiur check path - #445

Merged
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env
Jun 17, 2026
Merged

perf(ix): lazy, zero-copy anon env load for the Aiur check path#445
samuelburnham merged 1 commit into
mainfrom
sb/aiur-lazy-env

Conversation

@samuelburnham

@samuelburnhamsamuelburnham commented Jun 16, 2026

Copy link
Copy Markdown
Member

ix check --ixe deserialized the whole env eagerly: the Rust FFI materialized every constant and the Lean side built an object graph for all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB) that was ~104 GB peak RSS / ~159 s just to load.

Make the Lean Ixon.Env constants lazy and load them without copying:

  • LazyConstant is now an offset window (buf, off, len) into a shared backing buffer (+ optional materialized cache for the build path), parsed on demand. Only the checked closure is ever materialized.
  • New rs_de_env_lazy FFI: Env::parse_lazy_index walks the env once (reusing the existing parser, so every metadata variant incl. CallSite is handled) and returns per-const (addr, offset, len) windows into the buffer Lean passed in, plus name -> addr and per-Defn reducibility hints. No constant body is parsed or copied at load time. deEnvAnon reconstructs an Env of byte-window LazyConstants over that same buffer.
  • This is anon-aligned with the circuit: binder metadata (the ExprMetaArena) is parsed-and-discarded, since the typecheck circuit only consumes anonymous constants, blobs, and the per-Defn hint. The CLI's name -> addr map is kept so targets can still be named.
  • Pure-Lean getEnv/deEnv/rsDeEnv keep their full-metadata behavior for round-trip and the non-check loaders; only the check path (CheckCmd) switches to deEnvAnon.

Consumers updated for the lazy const type: closure walk, IOBuffer ingress (ships rawBytes windows directly), shard partitioning, decompile, and the compile/commit env builders.

Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB peak RSS, 159 s -> 13.5 s. Nothing in circuit changes: same closure bytes, same in-circuit blake3 verification, same proof.

Builds on the Rust kernel lazy deserialization from #415

@samuelburnham
samuelburnhamforce-pushed the sb/aiur-lazy-env branch 2 times, most recently from a845811 to f27fbfbCompareJune 16, 2026 19:43

@arthurpaulinoarthurpaulino left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
The "perf(aiur)" tripped me up a bit, but the patch looks good.

samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
samuelburnham added a commit that referenced this pull request Jun 17, 2026
Merge the Ix-compiler benchmark and a new Aiur execute/prove benchmark into one
workflow (aiur-bench.yml). Per library env it runs 'ix compile' to a .ixe
(compile-throughput metrics) then STARK-checks selected constants over that same
.ixe via bench-typecheck (execute + prove metrics), combined into one bencher
report. bench-typecheck loads the env lazily (Ixon.deEnvAnon, #445) so Mathlib
statements check at ~10GB peak RSS instead of the ~100GB eager load. Constants
are inline in the workflow matrix. Replaces compile.yml.
`ix check --ixe` deserialized the whole env eagerly: the Rust FFI
materialized every constant and the Lean side built an object graph for
all of them up front, even to check one lemma. On mathlib.ixe (2.97 GB)
that was ~104 GB peak RSS / ~159 s just to load.
Make the Lean `Ixon.Env` constants lazy and load them without copying:
- `LazyConstant` is now an offset window `(buf, off, len)` into a shared
backing buffer (+ optional materialized cache for the build path),
parsed on demand. Only the checked closure is ever materialized.
- New `rs_de_env_lazy` FFI: `Env::parse_lazy_index` walks the env once
(reusing the existing parser, so every metadata variant incl.
`CallSite` is handled) and returns per-const `(addr, offset, len)`
windows into the buffer Lean passed in, plus `name -> addr` and
per-`Defn` reducibility hints. No constant body is parsed or copied at
load time. `deEnvAnon` reconstructs an `Env` of byte-window
`LazyConstant`s over that same buffer.
- This is anon-aligned with the circuit: binder metadata (the
`ExprMetaArena`) is parsed-and-discarded, since the typecheck circuit
only consumes anonymous constants, blobs, and the per-`Defn` hint. The
CLI's `name -> addr` map is kept so targets can still be named.
- Pure-Lean `getEnv`/`deEnv`/`rsDeEnv` keep their full-metadata behavior
for round-trip and the non-check loaders; only the check path
(`CheckCmd`) switches to `deEnvAnon`.
Consumers updated for the lazy const type: closure walk, IOBuffer
ingress (ships `rawBytes` windows directly), shard partitioning,
decompile, and the compile/commit env builders.
Measured on mathlib.ixe (same file, same target): 104.5 GB -> 4.5 GB
peak RSS, 159 s -> 13.5 s, and the lazy run additionally typechecks the
target rather than only resolving its address. Nothing in circuit
changes: same closure bytes, same in-circuit blake3 verification, same
proof.
@samuelburnham
samuelburnham enabled auto-merge (squash) June 17, 2026 15:45
@samuelburnham
samuelburnham merged commit e9699ee into mainJun 17, 2026
14 checks passed
@samuelburnham
samuelburnham deleted the sb/aiur-lazy-env branch June 17, 2026 15:52
@samuelburnhamsamuelburnham changed the title perf(aiur): lazy, zero-copy anon env load for the Aiur check pathperf(ix): lazy, zero-copy anon env load for the Aiur check pathJun 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@samuelburnham@arthurpaulino