Skip to content

[Onyx Audit] Batching mechanism feels overcomplicated #71207

@fabioh8010

Description

@fabioh8010

Overview

This issue is part of our current effort to audit the performance and scalability of Onyx.

During the Step 1: Objective Analysis we gathered a list of Perceived Problems we have exclusively about Onyx, that is, the problems in Onyx we imagine or have some evidences that that are pain points / performance bottenecks to Onyx, but we need more analysis to confirm if they really are and, if so, how much of a problem they are currently.

The main goal right now is to deep dive into each Perceived Problem, investigate/audit it and come up with findings, which we will use for the next discussions.

Problem

For Onyx.set() and Onyx.merge() functions, the process is basically this one:

  1. Changes are broadcasted to subscribers with OnyxUtils.broadcastUpdate().
  2. At the same, Storage.setItem()/Storage.mergeItem() is called to store the changes (according to the code this approach prioritizes fast UI changes without waiting for data to be stored in device storage). If the value is being removed, OnyxUtils.remove() will be called instead and do the same steps below.
  3. OnyxUtils.broadcastUpdate() notifies subscribers and writes current value to cache. OnyxUtils.scheduleSubscriberUpdate() is called to schedule the subscriber update.
  4. OnyxUtils.scheduleSubscriberUpdate() will first call Onyx.keyChanged() in the next tick to notify the Onyx.connect() subscribers. Then, it will use OnyxUtils.batchUpdates() to batch a Onyx.keyChanged() call that notify the withOnyx()/useOnyx() subscribers. Finally, it waits for both OnyxUtils.maybeFlushBatchUpdates() and the first Onyx.keyChanged() to resolve.

The major difference is that Onyx.merge() will queue multiple changes to the same Onyx key, and later batch them into just one.

For Onyx.update(), SET and MERGE operations are queued by their Onyx keys. Collection key changes are grouped to be used into Onyx.mergeCollection() calls.

This overall system of broadcasting and merging looks too complex at a first glance, and I'm not really sure we still need it with React concurrent and useOnyx().

Action Items

  1. Analyse how other state management libraries handle batching/setting/merging of multiple store updates, and compare with ours.
  2. Understand why we have all these complexities in our internals and evaluate what we could change or simplify.

Relevant Links

Step 1 Canvas: https://expensify.slack.com/docs/T02P6RS2ZK7/F09B668M1MG

Slack thread: https://expensify.slack.com/archives/C05LX9D6E07/p1757416584331869

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions