feat(worker): add WorkerDocxodus.prepare() comparison-path warmup#208
Merged
Conversation
createWorkerDocxodus() warms the .NET WASM runtime but does not exercise the comparison engine, so the first compareDocuments() pays a one-time warmup cost (comparison-assembly init + JIT of the diff/XML stack) — about 2x steady-state latency. Consumers worked around this by shipping seed .docx fixtures and running a throwaway compare for the side effect. Add an optional, idempotent prepare(): Promise<void> on WorkerDocxodus that pays this cost up front with no caller IO: - New Warmup() [JSExport] on DocumentComparer runs a real WmlComparer.Compare (+ GetRevisions) against two tiny seed documents built in-memory on the .NET side, forcing the full compare path to resolve and JIT. - New "prepare" worker message routes to it. - WorkerDocxodus.prepare() caches a single in-flight warmup promise, so repeated/concurrent calls share it and a compareDocuments() issued while prepare() is pending does not double-load. Verified by npm/tests/worker-prepare.spec.ts (page-level .wasm request monitoring + in-worker timing): after prepare() a real compare fetches no additional .wasm; warm first compare ~758ms vs cold ~1504ms; second prepare() resolves in <50ms; concurrent prepare+compare never double-loads. Refs JSv4/crowdsourced-redlines-js#2
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.
Problem
createWorkerDocxodus()warms the .NET WASM runtime but does not exercise the comparison engine, so the firstcompareDocuments()pays a one-time warmup cost (comparison-assembly initialization + JIT of the diff/XML stack) — roughly 2× the steady-state latency. There was no way to pay this ahead of a user action, so downstream apps (crowdsourced-redlines-js,react-docxodus-viewer, …) each reinvented a workaround: ship a pair of seed.docxfixtures and run a throwaway compare purely for the side effect.Tracking issue in the consumer: JSv4/crowdsourced-redlines-js#2
Fix
Add an optional, idempotent
prepare(): Promise<void>onWorkerDocxodus(option 2/3 from the issue — a.NET-side warmup with no caller IO):Warmup()[JSExport]onDocumentComparerruns a realWmlComparer.Compare(+GetRevisions) against two tiny seed documents built in-memory on the .NET side, forcing the full compare path to resolve and JIT. No seed fixtures shipped, no caller inputs."prepare"worker message routes to it.WorkerDocxodus.prepare()caches a single in-flight warmup promise so repeated/concurrent calls share it, and acompareDocuments()issued while aprepare()is pending does not double-load.prepare()is never called automatically — skip it and the first compare absorbs the warmup exactly as before.Proof (
npm/tests/worker-prepare.spec.ts, all green)Verified via page-level
.wasmrequest monitoring + in-workerperformance.now()timing:prepare(), a real compare triggers no additional.wasmfetchesprepare()makes the first real compare meaningfully fasterprepare()is idempotent — second call resolves <50mscompareDocuments()whileprepare()is in flight does not double-loadExisting
worker.spec.ts(create/version/compare) still pass — the harness change is additive.Surface touched
.NETWASM bridge (DocumentComparer.Warmup) · worker message (docxodus.worker.ts) · proxy (worker-proxy.ts) · types (types.ts) · test harness + new spec · README "First-call warmup" section · CHANGELOG.Out of scope (per issue)
<link rel=preload>manifest, service-worker caching, and a separateprepareViewer()for the renderer assemblies — follow-ups.🤖 Generated with Claude Code