Skip to content

Conversation

@ntucker
Copy link
Collaborator

@ntucker ntucker commented Jan 4, 2026

Motivation

Improve normalization performance, especially for data with many entities or deep nesting.

Solution

  • Replace .forEach() with for loops in schema normalization/denormalization paths for reduced function call overhead
  • Use Set instead of arrays in circular reference detection (getCheckLoop) for O(1) lookups instead of O(n)
  • Cache Map.get() results to avoid redundant lookups

Note

Improves hot-path normalization/denormalization performance.

  • Replace Object.keys(...).forEach with indexed for loops in EntityMixin.normalize() and Object schema helpers to reduce call/iterator overhead
  • Switch getCheckLoop circular reference tracking from object[] to Set<object> with cached Map.get() results for O(1) membership checks
  • Adds benchmarking profiling guidance (start:trace, start:deopt) and updates examples docs
  • Changeset: patch releases for @data-client/endpoint, @data-client/normalizr, @data-client/rest, @data-client/graphql, @data-client/react, @data-client/vue

Written by Cursor Bugbot for commit 154c4c3. This will update automatically on new commits. Configure here.

@changeset-bot
Copy link

changeset-bot bot commented Jan 4, 2026

🦋 Changeset detected

Latest commit: 154c4c3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@data-client/endpoint Patch
@data-client/normalizr Patch
@data-client/rest Patch
@data-client/graphql Patch
@data-client/react Patch
@data-client/vue Patch
@data-client/core Patch
@data-client/img Patch
example-benchmark Patch
normalizr-github-example Patch
normalizr-redux-example Patch
normalizr-relationships Patch
test-bundlesize Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Details
Benchmark suite Current: 154c4c3 Previous: ad50b97 Ratio
normalizeLong 525 ops/sec (±0.90%) 526 ops/sec (±1.05%) 1.00
denormalizeLong 291 ops/sec (±2.29%) 294 ops/sec (±2.20%) 1.01
denormalizeLong donotcache 936 ops/sec (±2.12%) 1040 ops/sec (±0.17%) 1.11
denormalizeShort donotcache 500x 1593 ops/sec (±0.87%) 1588 ops/sec (±0.45%) 1.00
denormalizeShort 500x 869 ops/sec (±1.48%) 868 ops/sec (±1.89%) 1.00
denormalizeShort 500x withCache 6585 ops/sec (±0.08%) 6577 ops/sec (±0.24%) 1.00
queryShort 500x withCache 2750 ops/sec (±0.10%) 2783 ops/sec (±0.12%) 1.01
buildQueryKey All 54340 ops/sec (±0.18%) 55271 ops/sec (±0.32%) 1.02
query All withCache 8036 ops/sec (±0.20%) 7952 ops/sec (±0.24%) 0.99
denormalizeLong with mixin Entity 286 ops/sec (±2.16%) 276 ops/sec (±2.07%) 0.97
denormalizeLong withCache 7154 ops/sec (±0.14%) 7400 ops/sec (±0.26%) 1.03
denormalizeLong All withCache 8080 ops/sec (±0.18%) 7711 ops/sec (±0.22%) 0.95
denormalizeLong Query-sorted withCache 8083 ops/sec (±0.51%) 7961 ops/sec (±0.16%) 0.98
denormalizeLongAndShort withEntityCacheOnly 1697 ops/sec (±0.18%) 1769 ops/sec (±0.39%) 1.04
getResponse 5603 ops/sec (±1.46%) 5721 ops/sec (±1.20%) 1.02
getResponse (null) 7296864 ops/sec (±0.74%) 7195694 ops/sec (±0.74%) 0.99
getResponse (clear cache) 276 ops/sec (±2.17%) 268 ops/sec (±2.29%) 0.97
getSmallResponse 3076 ops/sec (±0.42%) 3148 ops/sec (±0.15%) 1.02
getSmallInferredResponse 2360 ops/sec (±0.13%) 2242 ops/sec (±0.14%) 0.95
getResponse Collection 5309 ops/sec (±1.05%) 5821 ops/sec (±1.08%) 1.10
get Collection 5509 ops/sec (±0.17%) 5744 ops/sec (±0.35%) 1.04
get Query-sorted 6624 ops/sec (±0.21%) 6610 ops/sec (±0.44%) 1.00
setLong 549 ops/sec (±0.13%) 545 ops/sec (±0.19%) 0.99
setLongWithMerge 250 ops/sec (±0.42%) 246 ops/sec (±0.20%) 0.98
setLongWithSimpleMerge 268 ops/sec (±0.17%) 261 ops/sec (±0.11%) 0.97
setSmallResponse 500x 949 ops/sec (±0.09%) 962 ops/sec (±0.10%) 1.01

This comment was automatically generated by workflow using github-action-benchmark.

@codecov
Copy link

codecov bot commented Jan 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.30%. Comparing base (096f6d8) to head (154c4c3).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #3684   +/-   ##
=======================================
  Coverage   98.29%   98.30%           
=======================================
  Files         148      148           
  Lines        2582     2589    +7     
  Branches      501      502    +1     
=======================================
+ Hits         2538     2545    +7     
  Misses         10       10           
  Partials       34       34           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ntucker ntucker marked this pull request as ready for review January 4, 2026 15:47
@ntucker ntucker changed the title enhance: Peformance optimization enhance: Minor peformance optimization Jan 4, 2026
@ntucker ntucker merged commit 53de2ee into master Jan 4, 2026
24 checks passed
@ntucker ntucker deleted the optimizations branch January 4, 2026 15:51
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.

2 participants