Skip to content

perf(wasm): cache container kind() on JS wrappers - #1085

Merged
zxch3n merged 1 commit into
mainfrom
perf/wasm-kind-cache
Sep 4, 2026
Merged

zxch3n merged 1 commit into
mainfrom
perf/wasm-kind-cache

Conversation

@zxch3n

@zxch3n zxch3n commented Sep 3, 2026 •

Copy link
Copy Markdown
Member

Stack: 2/6 — merge order: #1093 → #1085 → #1086 → #1087 → #1090 → #1091

Summary

kind() on container wrappers (LoroMap/LoroList/LoroText/LoroTree/LoroMovableList/LoroCounter) returns a constant string per class, but every call crossed into WASM and allocated a fresh JS string via getStringFromWasm0. On a real document with ~70k containers, loro-mirror-style traversal called kind() 230k times per full read (and id 333k times; the id cache already landed in #1073).

This extends the existing container_id_cache_patch.js mechanism with a class-level memo for kind(). Reads after free() still raise wasm-bindgen's null-pointer error (the memo is bypassed for a zero __wbg_ptr), and Rust-side kind() reads in js_to_container share the same memo.

Measured (scripts/measure-container-id.cjs, 1M repeated reads of one wrapper)

case before after
same-wrapper-repeated-kind 164.5 ms, 1,000,000 string decodes ~1.0 ms, 0 decodes
mirror-reuse-wrapper (id + kind + toJSON, 20k containers) 51.1 ms, 63,333 decodes 42.4 ms, 23,333 decodes

Tests

  • tests/container_id_cache.test.ts: repeated kind() calls return the same string with zero additional wasm string decodes; at most one decode per container class; post-free() reads still throw.
  • Full wasm suite: 26 files / 349 tests pass; tsc --noEmit clean.

Wasm binary size

No change — this is a pure JS-glue patch.

Part 1 of the bulk-read series; the follow-up (per-container/range deep reads) stacks on this branch.

@github-actions

github-actions Bot commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

WASM Size Report

  • Original size: 3107.39 KB
  • Gzipped size: 1030.04 KB
  • Brotli size: 722.57 KB

kind() returns a constant string per container class but the wasm-bindgen
glue crossed into WASM and allocated a fresh JS string on every call.
Memoize it once per class next to the existing per-wrapper id cache.

Measured with scripts/measure-container-id.cjs (1M repeated reads):
164.5 ms -> 1.0 ms, wasm string decodes 1,000,000 -> 0.
@zxch3n
zxch3n force-pushed the perf/wasm-kind-cache branch from a9c2161 to 635bdf7 Compare September 4, 2026 12:17
@zxch3n
zxch3n merged commit 8874574 into main Sep 4, 2026
1 check passed
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.

1 participant