Skip to content

AST node layout: shrink Inline/Block/Attr/text storage (epic bd-4x6kih4c) - #1192

Draft
cscheid wants to merge 5 commits into
mainfrom
feature/ast-node-layout
Draft

cscheid wants to merge 5 commits into
mainfrom
feature/ast-node-layout

Conversation

@cscheid

@cscheid cscheid commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

Integration branch for epic bd-4x6kih4c. Draft: stages land here as they complete.

Why

A study (bd-akgst1fi, claude-notes/plans/2026-11-12-ast-string-storage-study.md) measured the parsed AST of claude-notes/plans (26.3 MiB of Markdown) at 2,304 MiB of heap, 88x the source. 89% of that is Vec<Inline> buffers: Inline is 360 bytes (192 on wasm32), sized by Link, and every Space pays for it.

The study recommends against adding a lifetime to the AST and for fixing node layout instead.

Stages

  • Study doc and ast-memory census tool in perf-harness
  • bd-xrfun6mn: box cold Inline variants. Inline 360 → 64 bytes; AST heap 2,304 → 678 MiB (87.7× → 25.8× of source); peak RSS 2.75 → 0.87 GiB
  • bd-09g8zl30: box cold Block variants
  • bd-gz80k6c6: slim Attr + AttrSourceInfo for the empty case
  • bd-cwprgmo2: reader allocation fast paths, adjacent-Original source-info hull
  • bd-v6cug77d: small-string type for text fields (ecow first)
  • bd-9iyh0220: quarto-source-map u32 offsets, shared file content
  • bd-r17a0k7v: wasm32 AST-memory tracking

Measuring

cargo build --release -p perf-harness --bin ast-memory
./target/release/ast-memory claude-notes/plans

🤖 Generated with Claude Code

t and others added 3 commits November 12, 2026 13:21
… (bd-akgst1fi)

ast-memory parses a directory of .md/.qmd with pampa's reader, retains
every AST, and reports allocator traffic, a census of text-carrying
fields, Str shape, and a text-run what-if. The study doc records the
measurements on claude-notes/plans (AST heap = 88x source, 89% of it
Vec<Inline> buffers) and the recommendation to fix node layout rather
than add a lifetime to the AST.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…study

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ing decisions

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

t and others added 2 commits November 12, 2026 14:16
…6mn)

Every element of a Vec<Inline> occupies size_of::<Inline>() bytes, and
most inlines are Str and Space. Link (352 bytes) set that size for all
of them. Box the payloads of the variants larger than Str: Quoted, Cite,
Code, Math, RawInline, Link, Image, Span, Shortcode, Attr, Insert,
Delete, Highlight, EditComment and Custom. A const assertion holds
Inline at 8 words (64 bytes native, 32 on wasm32).

On claude-notes/plans (26.3 MiB) with perf-harness ast-memory:
Vec<Inline> buffers 2058 -> 366 MiB, AST heap 2304 -> 678 MiB (87.7x ->
25.8x of source), peak RSS 2.75 -> 0.87 GiB, parse wall 7.7 -> 6.5 s.

Serde is unaffected (Box<T> serializes as T). Call sites change
mechanically: constructions gain Box::new, destructuring patterns on
boxed payloads become a binding plus field access, and or-patterns
mixing boxed and unboxed variants are split.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to 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