perf(table-core): shape-stable row/cell/column/header instances - #6569
perf(table-core): shape-stable row/cell/column/header instances#6569KevinVandy wants to merge 2 commits into
Conversation
Keep one hidden class per instance kind for the whole instance lifetime so V8 property access stays monomorphic: - memoized prototype APIs store memo state in a pre-declared `_memos` holder (plus dedicated `memoSlot`s for render-hot APIs) instead of installing `_memo_<fnKey>` own properties on first call - rows and cells allocate through per-table constructor functions so every field lives in-object; a discarded warmup instance per table pre-marks declared fields mutable to avoid field-constness deopt waves - all post-construction own-property additions declared up front: grouping row fields (the `Object.assign` + per-row `getValue` closure becomes a fixed-arity prototype override), `_cellsCache`, `originalSubRows`, pinned `position` marks; sorted clones rebuilt via `constructRow` - eager per-row cache maps made lazy (`_uniqueValuesCache`, `_groupingValuesCache`); filter maps start as a shared frozen empty map Browser (100k rows, vs 9.1.2): grouped stage -23%, heap -20%; Node construction -21..-35%; steady-state access at parity; %HaveSameMap shape gate passes (fails on 9.1.2). Adds tests/unit/shapeStability.test.ts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit b164a93
☁️ Nx Cloud last updated this comment at |
🚀 Changeset Version Preview1 package(s) bumped directly, 0 bumped as dependents. 🟩 Patch bumps
|
Summary
Keeps one V8 hidden class per instance kind (row, cell, column, header) for the whole instance lifetime, so property access across rows/cells stays monomorphic instead of forking into megamorphic ICs. This is the fix for the
Object.assign-on-rows / lazy-memo-property pattern flagged in the Discord perf thread._memosholder (dedicatedmemoSlots for the render-hot ones:cell.getContext,row.getAllCells,row.getVisibleCells, ...) instead of installing_memo_<fnKey>own properties on first call, which was the main shape-forker.new TableRow(...)instead ofObject.create(proto)+ assigns): every field lives in-object, no out-of-line property array that reallocates as fields are added. This flipped construction from a regression into the largest win and is most of the memory improvement.warmInstanceShape): rewrites each declared field once at prototype creation so V8 never assumes field constness and deopts on the first real write (grouped row fields, memo slots, pinnedposition).Object.assign(row, {..., getValue: closure})becomes value writes + a fixed-arity prototypegetValueoverride;_groupedRowskept besideleafRowsto preserve exact tree-data aggregation),_cellsCache,originalSubRows, row/cell pinnedposition; sorted clones rebuilt viaconstructRow; worker rebuild seeds caches instead of an own closure._uniqueValuesCache/_groupingValuesCacheallocate on first use;columnFilters(Meta)start as a shared frozen empty map (public types unchanged, zero per-row allocation).tests/unit/shapeStability.test.ts: own-key-order identity across leaf/group/pinned/cloned rows and cells, before and after every API call (the natives-free proxy for map identity), plus groupedgetValuegoldens.Results (vs 9.1.2, 100k rows unless noted)
%HaveSameMapshape gate across rows/cells/columns/headersbench:row-model grouping:sum)Full monorepo CI and all 388 example e2e projects pass. Benchmark harness (shape gate, access sweep, A/B recipe) lives in the benchmark-examples repo.
Notes for review
Row_ColumnGroupinggained defaulted generics (<TFeatures, TData>) to typeleafRows/_groupedRows.position?: 'top' | 'bottom'is now typed onRow_RowPinning.🤖 Generated with Claude Code