fix: oversubscription perps top movers#33150
Conversation
PR template — items to address before "Ready for review"Warnings — informational, address before merging:
See docs/readme/ready-for-review.md for the full Definition of Ready for Review. |
🧪 Flaky unit test detectionRun history flaky detectionHistorical failure rate is a hint, not proof — review each suggestion in context. See the flaky-test-detection skill for the full pattern reference and manual audit workflow. Failures / runs sampled per window:
AI-detected flaky patterns
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #33150 +/- ##
==========================================
+ Coverage 84.31% 84.38% +0.06%
==========================================
Files 6080 6129 +49
Lines 162378 163629 +1251
Branches 39577 39903 +326
==========================================
+ Hits 136905 138074 +1169
- Misses 16021 16046 +25
- Partials 9452 9509 +57 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…taMask/metamask-mobile into fix/oversubscription-perps-top-movers
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9f36d83. Configure here.
geositta
left a comment
There was a problem hiding this comment.
Nice work overall addressing the root cause. Before approving, please fix the stale market data path. I also recommend narrowing the active tab update so this performance change does not rerender every loaded Explore feed.
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
Tag selection rationale:
Performance Test Selection: |
|
⚡ Performance Test Results
✅ All tests passed · 2 tests · 1 device 📱 Devices tested (1)Android: Google Pixel 8 Pro (v14.0) ✅ Passed Tests (2)
Branch: |




Description
Problem
The Now-tab perps movers strip subscribed to live prices for all ~329 markets and, on every ~3s push, rebuilt/re-sorted the full set and re-rendered — just to show the top 12 pills. Since Explore tabs never unmount, this kept running even on other tabs or after leaving Explore.
Why we keep the full-market subscription
Subscribing to only the 12 displayed symbols would break ranking: a market outside the top 12 can move into it, and we'd miss that price change. Correct live re-ordering requires watching every market.
The middle ground
The WebSocket already pushes all markets regardless of subscription — the real cost was the unconditional
setState, the per-tick re-sort, and new object identities per tick. The newusePerpsLiveMovershook merges every tick into a ref (no render per tick) and derives the displayed top-12 synchronously in render, so base-data loads and gainers/losers toggles reflect immediately with no empty frame. Live ticks only trigger a render when the displayed top-12 actually changes (via asymbol:formattedPercentfingerprint), reusing prior item references so unchanged pills skip re-render.The full rank/filter/sort pass itself is also throttled to a configurable interval (
recomputeIntervalMs, 10s on the Now tab): ticks arriving inside the interval accumulate losslessly in the ref, and at most one ranking pass runs per interval using the freshest data. Idle ticks cost only a cheap ref merge. On (re)subscribe — mount, tab resume, symbol-set change — the throttle anchor resets so the stream's cached snapshot surfaces promptly instead of waiting out a full interval.On top of that, the subscription pauses entirely when not visible: an
ExploreActiveTabContexttellsPerpsBlockwhether the Now tab is active, combined withuseIsFocused()for leaving Explore. The same focus gating is applied to the What's Happening detail view's perps price hook. Disabling freezes the last-known data rather than clearing it, so nothing blanks out and it refreshes immediately on resume.Changelog
CHANGELOG entry: improve performance on Perps Movers in explore
Related issues
Fixes:
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Performance checks (if applicable)
trace()for usage andaddTokenfor an exampleFor performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Note
Medium Risk
Touches live perps ranking, WebSocket subscription lifecycle, and Explore tab rendering; behavior is heavily tested but incorrect gating could show stale movers or miss updates.
Overview
Reduces Explore perps movers overhead by replacing per-tick
usePerpsLivePrices+ full re-sort inPerpsBlockwith a newusePerpsLiveMovershook that still watches all markets (so top-12 ranking stays correct) but merges ticks into a ref, only re-renders when the visible movers fingerprint changes, batches ranking with a 10s interval, and preserves pill object identity for unchanged symbols.Pauses live work when Explore isn’t visible:
ExploreActiveTabContext+ anExploreTabssubtree isolate tab state so switching tabs doesn’t re-render inactive tab feeds;PerpsBlockenables the movers subscription only when the screen is focused and the Now tab is active. What’s Happening detail pauses perps prices the same way by passing an empty symbol list while unfocused.Tests cover the new context, tab-switch render behavior, live-movers hook edge cases, and subscription gating on Now tab.
Reviewed by Cursor Bugbot for commit bf62bf3. Bugbot is set up for automated code reviews on this repo. Configure here.