Repository navigation
perf: derive deferred-open stand-ins in the renderer instead of shipping them - #321
Merged
Merged
Conversation
…ing them A deferred open attached a structural stand-in mdast node to all 43,970 blocks of the huge document and sent them across IPC (about 11 MB of the 25 MB payload). Engine-owned blocks never read theirs, and the rest are re-parsed from source when enriched. parseDocument now sends nodes: null with nodesEnrichment 'deferred', and blockSpansFromWire derives each stand-in from the block's kind and source when it is first read (memoised, own enumerable getter so clones and spreads still see a value). enrichSpanNone and finalizeEngineAdapterSpan build stand-ins the same lazy way. The wire validator accepts a deferred open without nodes and still refuses a full one without them. Huge open payload 24.98 -> 14.07 MB; main IPC send ~71 -> ~36 ms; packaged Linux open ~1.67 -> ~1.55 s (interleaved runs).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
On a deferred open (
@roobli/md, the default), main no longer attaches a structural stand-in mdast node to every block or ships them over IPC.parseDocumentsendsnodes: nullwithnodesEnrichment: 'deferred'.blockSpansFromWirethen derives each block's stand-in from its kind and source the first time something readsspan.node. Engine-owned blocks never read it; the rest are re-parsed from source when they're enriched.lazyNodeSpan(fields, build)returns a span whosenodeis a memoised getter. The getter is an own, enumerable property, sostructuredClone, spreads andtoEqualstill see a plain value and theBlockSpancontract is unchanged.standInNodeFor(kind, markdown)exposes the existingstandInNode.enrichSpanNoneandfinalizeEngineAdapterSpanbuild stand-ins the same lazy way, so main never builds them for the wire either.deferredopen may omit nodes. Afullopen without nodes is still refused. Incremental saves are unchanged (no nodes, nonodesEnrichment).Measured (huge, 8 MB, 43,970 blocks, Linux box)
f25d1fe)publish(IPC send), profiledparseDocument, profiledBENCH_RUNS=5, interleaved ×2*outlier
Honest note: building the stand-ins was only ~10 ms of
parseDocument, so main parse time doesn't move. Its cost is the engine split pluscanSkipDialectEnrich/engineSemanticKeyon every block. The win is the payload and IPC: ~100–150 ms of open on huge.Tests
pnpm typecheckandpnpm testpass.blockSpansFromWire.nodeswere non-null.