Skip to content

Conversation

@gwansikk
Copy link

@gwansikk gwansikk commented Jan 8, 2026

🎯 Changes

I'm using TanStack Form for a large-scale form application. The project manages user-addable table rows (each row containing multiple inputs) along with 20-30 additional fields on a single page. During form submission, UI blocking of 2.7 seconds, and in some cases 8-10 seconds, was occurring.

After profiling, I identified that the __flush_internals function in @tanstack/store was causing a performance bottleneck due to excessive recursive calls.

image image2

Change the data structure of __depsThatHaveWrittenThisTick from Array to Set, replacing O(n) includes() with O(1) has() for duplicate checking.

- current: [] as Array<Derived<unknown> | Store<unknown>>,
+ current: new Set<Derived<unknown> | Store<unknown>>(),

- if (__depsThatHaveWrittenThisTick.current.includes(derived)) {
+ if (__depsThatHaveWrittenThisTick.current.has(derived)) {

- __depsThatHaveWrittenThisTick.current.push(derived)
+ __depsThatHaveWrittenThisTick.current.add(derived)

- __depsThatHaveWrittenThisTick.current = []
+ __depsThatHaveWrittenThisTick.current.clear()

Benchmark

Scale Stores Deriveds Winner Improvement
Small 20 60 Array 1.98x faster
Medium 50 200 Set 1.13x faster
Large 100 500 Set 2.16x faster
Very Large 200 1000 Set 3.66x faster
Extreme 500 2500 Set 8.43x faster
Detailed Results
Scale Method hz mean (ms) min (ms) max (ms) p99 (ms) rme samples
Small Array.includes() 35,907.52 0.0278 0.0262 0.2352 0.0365 ±0.22% 17,954
Small Set.has() 18,101.88 0.0552 0.0501 2.1192 0.0736 ±1.14% 9,051
Medium Array.includes() 3,044.06 0.3285 0.3119 0.5857 0.3871 ±0.29% 1,523
Medium Set.has() 3,450.28 0.2898 0.2742 0.5368 0.3285 ±0.24% 1,726
Large Array.includes() 398.89 2.5070 2.4501 2.7756 2.7168 ±0.34% 200
Large Set.has() 861.65 1.1606 1.0971 1.5831 1.2923 ±0.39% 431
Very Large Array.includes() 112.81 8.8648 8.7488 9.1669 9.1669 ±0.25% 57
Very Large Set.has() 413.38 2.4191 2.2845 2.9173 2.6126 ±0.44% 207
Extreme Array.includes() 20.31 49.2265 47.9097 51.6416 51.6416 ±1.41% 11
Extreme Set.has() 171.27 5.8386 5.5525 6.4998 6.4998 ±0.55% 86

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

@gwansikk
Copy link
Author

gwansikk commented Jan 8, 2026

This is the first in a series of performance improvement PRs.
All tests pass, but feedback is welcome if I've missed anything.

I'd like to better understand the internals and help solve the pyramid dependency problem more elegantly.

@gwansikk gwansikk changed the title perf(store): optimize __flush_internals refactor(store): optimize __flush_internals Jan 8, 2026
@gwansikk gwansikk changed the title refactor(store): optimize __flush_internals refactor(store): replace Array.includes() with Set.has() in __depsThatHaveWrittenThisTick Jan 8, 2026
@gwansikk gwansikk changed the title refactor(store): replace Array.includes() with Set.has() in __depsThatHaveWrittenThisTick refactor(store): replace array with set in __depsThatHaveWrittenThisTick Jan 8, 2026
@gwansikk gwansikk marked this pull request as ready for review January 8, 2026 14:38
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