Problem
usePolicyForMovingExpenses subscribed to the active policy with activePolicySelector, which returns the whole policy object. useOnyx deep-compares a selector's output to keep its reference stable, so every instance of the hook deep-compared an entire workspace — employeeList, customUnits, rules — on every Onyx merge touching its key. On Search that cost is multiplied twice over: useOnyx re-points policy_* at the snapshot_<hash> key so every snapshot merge notifies it, and each visible transaction row reaches the hook about four times (TransactionListItemWide, TransactionListItemInner, TransactionItemRowWide, and usePolicyForTransaction via useTransactionInlineEdit). Profiling in dev measured 3.2–6.6ms per compare with every single one concluding "equal" — pure waste on the JS thread inside keyChanged. On a large customer account with an 11k-member policy, deepEqual checks on that policy's reports took 100–300ms.
Solution
Move the subscription into a new ActivePolicyProvider, mounted in OnyxListItemProvider whose stated purpose is shared subscriptions for list items. The provider holds the single NVP_ACTIVE_POLICY_ID and activePolicySelector subscription and exposes {activePolicyID, activePolicy} through context, so the whole-policy deep compare happens once per merge instead of once per hook instance. usePolicyForMovingExpenses now reads useActivePolicy() and drops its own two useOnyx calls. On the 11k-member account this brings the 100–300ms of deepEqual work down to roughly 30ms.
Notes
This PR is currently a draft and its title still reads [WIP] Onyx deepEqual profiling probe, which describes an earlier investigation rather than the change now in the diff (+41/−6 across 3 files: the new ActivePolicyProvider, its registration in OnyxListItemProvider, and the usePolicyForMovingExpenses switch to context). The title is worth updating before review.
PR
#98299
Issue Owner
Current Issue Owner: @TMisiukiewicz
Problem
usePolicyForMovingExpensessubscribed to the active policy withactivePolicySelector, which returns the whole policy object.useOnyxdeep-compares a selector's output to keep its reference stable, so every instance of the hook deep-compared an entire workspace —employeeList,customUnits,rules— on every Onyx merge touching its key. On Search that cost is multiplied twice over:useOnyxre-pointspolicy_*at thesnapshot_<hash>key so every snapshot merge notifies it, and each visible transaction row reaches the hook about four times (TransactionListItemWide,TransactionListItemInner,TransactionItemRowWide, andusePolicyForTransactionviauseTransactionInlineEdit). Profiling in dev measured 3.2–6.6ms per compare with every single one concluding "equal" — pure waste on the JS thread insidekeyChanged. On a large customer account with an 11k-member policy,deepEqualchecks on that policy's reports took 100–300ms.Solution
Move the subscription into a new
ActivePolicyProvider, mounted inOnyxListItemProviderwhose stated purpose is shared subscriptions for list items. The provider holds the singleNVP_ACTIVE_POLICY_IDandactivePolicySelectorsubscription and exposes{activePolicyID, activePolicy}through context, so the whole-policy deep compare happens once per merge instead of once per hook instance.usePolicyForMovingExpensesnow readsuseActivePolicy()and drops its own twouseOnyxcalls. On the 11k-member account this brings the 100–300ms ofdeepEqualwork down to roughly 30ms.Notes
This PR is currently a draft and its title still reads
[WIP] Onyx deepEqual profiling probe, which describes an earlier investigation rather than the change now in the diff (+41/−6 across 3 files: the newActivePolicyProvider, its registration inOnyxListItemProvider, and theusePolicyForMovingExpensesswitch to context). The title is worth updating before review.PR
#98299
Issue Owner
Current Issue Owner: @TMisiukiewicz