Problem
OnyxCache.getCollectionData() calls isEmptyObject(snapshot) on every read to decide whether to return the collection or the empty-collection fallback. Profiling the Search page showed this check dominates read time and scales with collection size — e.g. ~1ms per read on report_, transactions_, and reportActions_, totaling 400–700ms on dev and 500–1000ms on staging/large accounts.
Solution
Store the shared frozen-empty object (FROZEN_EMPTY_COLLECTION) as the snapshot for empty collections instead of a fresh {}. The read path detects emptiness with a single snapshot === FROZEN_EMPTY_COLLECTION reference comparison (no key scan), and non-empty collections return the snapshot directly without calling isEmptyObject. Emptiness is determined once at snapshot-build time in rebuildCollectionSnapshot rather than on every read.
PR
Expensify/react-native-onyx#812
Issue Owner
Current Issue Owner: @TMisiukiewicz
Problem
OnyxCache.getCollectionData()callsisEmptyObject(snapshot)on every read to decide whether to return the collection or the empty-collection fallback. Profiling the Search page showed this check dominates read time and scales with collection size — e.g. ~1ms per read onreport_,transactions_, andreportActions_, totaling 400–700ms on dev and 500–1000ms on staging/large accounts.Solution
Store the shared frozen-empty object (
FROZEN_EMPTY_COLLECTION) as the snapshot for empty collections instead of a fresh{}. The read path detects emptiness with a singlesnapshot === FROZEN_EMPTY_COLLECTIONreference comparison (no key scan), and non-empty collections return the snapshot directly without callingisEmptyObject. Emptiness is determined once at snapshot-build time inrebuildCollectionSnapshotrather than on every read.PR
Expensify/react-native-onyx#812
Issue Owner
Current Issue Owner: @TMisiukiewicz