Skip to content

perf: materialize query results once - #320

Open
huytdps13400 wants to merge 1 commit into
margelo:mainfrom
huytdps13400:fix/310-cache-query-results
Open

perf: materialize query results once#320
huytdps13400 wants to merge 1 commit into
margelo:mainfrom
huytdps13400:fix/310-cache-query-results

Conversation

@huytdps13400

Copy link
Copy Markdown

Summary

  • materialize the hybrid results getter once when building the JS-compatible rows object
  • make _array, length, and item(index) share that single materialized array
  • cover getter reads plus 60, 1,000, and 10,000-row sync/async access, including NULL, BLOB, and out-of-range behavior

Fixes #310.

Why

results is a HybridObject getter that returns the native result vector by value. The previous rows.item(index) closure evaluated that getter for every item, so traversing N rows requested N additional full result vectors. Caching the first materialization preserves the public result shape while removing the quadratic copy pattern.

Benchmark

Synthetic getter-copy benchmark using Bun 1.3.14, six-column rows, one warm-up plus 20 measured iterations. The getter conservatively returns a shallow array copy; timings include wrapper construction and the named consumer.

Rows Consumer Main median / p95 This PR median / p95 Getter reads
60 full item() traversal 0.0112 / 0.0150 ms 0.000709 / 0.00504 ms 62 → 1
1,000 full item() traversal 0.579 / 1.002 ms 0.00250 / 0.00313 ms 1,002 → 1
10,000 full item() traversal 30.014 / 32.130 ms 0.01396 / 0.01504 ms 10,002 → 1

For direct _array and length consumers, getter reads drop from 2 to 1 at every size. At 10,000 rows their median wrapper-plus-access time drops from about 0.014 ms to 0.006–0.008 ms in the same conservative benchmark.

The committed real-device harness coverage also traverses all items for 60, 1,000, and 10,000 rows through both execute and executeAsync.

Verification

  • bun typecheck
  • bun lint
  • bun sqlite build
  • iOS simulator, Debug/Hermes: unit 35/35, TypeORM 1/1, sqlite-vec 35/35
  • Android API 35 emulator, Debug/Hermes: unit 35/35, TypeORM 1/1, sqlite-vec 35/35
  • Android assembleDebug succeeded across all configured ABIs
  • regression test verified red on main (5 getter reads for two rows) and green on this branch (1 read)

bun sqlite test --runInBand is currently blocked before test discovery by the repository's React Native 0.85 preset migration (react-native now requires @react-native/jest-preset). The real React Native harness suites above pass on both platforms.

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.

perf: avoid repeated full query-result copies

1 participant