Skip to content

Hot-loop performance: grid-layer micro-costs - #4606

Merged
lbwexler merged 2 commits into
developfrom
hot-loop-perf-5
Aug 21, 2026
Merged

Hot-loop performance: grid-layer micro-costs#4606
lbwexler merged 2 commits into
developfrom
hot-loop-perf-5

Conversation

@lbwexler

Copy link
Copy Markdown
Member

Fifth batch in the stack (#4600 β†’ #4602 β†’ #4603 β†’ #4604 β†’ this) - pure internal reorg, no API or behavior changes. Deliberately trimmed to three items with real multipliers (a cellClass static-array precompute and a ZoneGridRenderer cleanup were built, then rejected as cheap-regime churn - rationale in the working notes).

  • GridModel.getStateForColumn: native find with a plain predicate - was a lodash {colId} matcher allocation per call, called per visible column per transaction via Grid.syncData (and from autosize / h-scrollbar paths).
  • GridHScrollbar: the three ag-Grid viewport elements resolve once on link - was one to two querySelector DOM traversals per scroll event, on the frame-critical path.
  • managedRenderer: fixed two-arg forward - was an arguments object + Function.apply per render call of every wrapped renderer, including per record Γ— column during autosize sampling. Wrapped renderer types (ColumnRenderer, GroupRowRenderer) cap at two params, and the fixed signature is easier to reason about than the reflective forward.

Validated in Toolbox: standard grid render/sort, column chooser hide/show round-trip, zone grid rendering. Zero console errors.

Note: the columnStateReaction in-place-mutation bug found during this work shipped separately as #4605 against develop.

Base automatically changed from hot-loop-perf-4 to develop August 21, 2026 19:56
* GridModel.getStateForColumn uses a native find with a plain predicate - was a lodash {colId} matcher allocation per call, called per visible column per transaction via Grid.syncData.
* GridHScrollbar resolves its three ag-Grid viewport elements once on link - was one to two querySelector DOM traversals per scroll event.
* managedRenderer forwards a fixed two-arg call - was an arguments object + Function.apply per render call of every wrapped renderer, incl. per record x column during autosize sampling. Wrapped renderer types cap at two params.
Only rendered, selected, and searched records are ever asked for an agId, but every record paid for one on load. Deferring the concat to first read cuts 6.3MB of retained heap per 200k-record store (45.9 -> 39.6MB, measured with forced gc); timing gain is ~2ms per load, within harness noise. A store whose every agId gets touched (e.g. a find-field query over the full store) lands ~2MB above the eager version - the right trade for grids where a few hundred rows of many are ever rendered.
@lbwexler
lbwexler merged commit bf7361d into develop Aug 21, 2026
3 checks passed
@lbwexler
lbwexler deleted the hot-loop-perf-5 branch August 21, 2026 19:58
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