Commit f5e5f6d
- perf(predict): fix JS-thread FPS collapse on market details with live
prices cp-7.82.0 (#31801)
## **Description**
This PR fixes severe JS-thread performance degradation on the Predict
market details screen (`PredictMarketDetails` /
`PredictGameDetailsContent`). When opening a market with a live price
feed — most noticeably a live soccer game — the JS thread FPS would
collapse to near 0, making the screen unusable.
**Reason for the change:** The live Polymarket WebSocket price stream
drives high-frequency updates. The code was (1) doing an
`O(subscriptions × tokens)` `new Set(key.split(','))` allocation on
*every* incoming price message, and (2) re-rendering the entire details
screen on every single message because nothing was throttled or
memoized. Profiling showed `performWorkOnRoot` (React render) consuming
~70% of the trace, with `new Set()`/`Object.assign`/`JSON.stringify`
allocation churn dominating self-time.
**Improvements:**
- **`WebSocketManager`**
- Precompute the parsed `Set<tokenId>` per subscription once at
subscribe time instead of rebuilding it (`new Set(key.split(','))`) on
every message. This removes the single largest self-time hotspot.
- Coalesce/throttle price emission with a leading + trailing edge
(250ms, mirroring the existing orderbook throttle) so subscribers are
notified at most ~4×/sec instead of at the full WebSocket message rate.
- Clean up the new timer/buffer/Set state on disconnect and full
cleanup.
- **`useLiveMarketPrices`** — skip the state update entirely when an
incoming tick carries no actual value change
(`price`/`bestBid`/`bestAsk`), preventing redundant re-renders.
- **`usePredictPrices`** — memoize the per-render
`JSON.stringify(queries)` so it only runs when the queries change.
- **`useOpenOutcomes`**
- Disable the live price subscription for game markets, where its result
is never rendered (the game branch runs its own subscriptions). Removed
a redundant full-screen re-render source.
- Preserve object identity for outcomes/tokens whose computed price did
not change, so only rows that actually changed get a new reference.
- **`PredictMarketDetails`** — memoize
`handleBackPress`/`handleBuyPress`/`handleClaimPress` so stable
callbacks no longer defeat child memoization.
- **`PredictGameDetailsContent`** and **`PredictMarketOutcome`** — wrap
in `React.memo` so a parent re-render no longer re-renders these
subtrees/rows when their props are unchanged.
**Result:** JS-thread FPS went from ~0 → mid-50s on live game events,
and regular markets from ~25–35 → comparable smoothness, with re-renders
now scoped to the components whose data actually changed.
## **Changelog**
CHANGELOG entry: Fixed severe performance degradation on the Predict
market details screen for markets with live price updates.
## **Related issues**
Fixes:
[PRED-1014](https://consensyssoftware.atlassian.net/browse/PRED-1014)
## **Manual testing steps**
```gherkin
Feature: Predict market details performance with live prices
Scenario: user opens a live game market
Given a live soccer game market is available in Predict
And the JS-thread FPS monitor / performance overlay is enabled
When the user opens the PredictGameDetailsContent screen
Then the screen remains responsive
And the JS-thread FPS stays in a healthy range (not collapsing toward 0)
Scenario: user opens a regular market with live prices
Given a regular open market with live price updates is available in Predict
When the user opens the PredictMarketDetails screen
Then the outcomes list updates live without re-rendering unchanged rows
And the JS-thread FPS stays in a healthy range
Scenario: live prices still update correctly
Given the user is on a market details screen
When the underlying token prices change over the WebSocket feed
Then the displayed prices/odds update to reflect the new values
```
## **Screenshots/Recordings**
### **Before**
<!-- [screenshots/recordings] -->
https://github.com/user-attachments/assets/1cc444f5-a693-4584-80f8-072305a3147c
### **After**
<!-- [screenshots/recordings] -->
https://github.com/user-attachments/assets/1fe95b3c-1fb4-4fa0-a794-8450cbe08f88
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
[PRED-1014]:
https://consensyssoftware.atlassian.net/browse/PRED-1014?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
[716f9a8](716f9a8)
[PRED-1014]:
https://consensyssoftware.atlassian.net/browse/PRED-1014?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
Co-authored-by: Luis Taniça <matallui@gmail.com>
1 parent 1f49900 commit f5e5f6d
8 files changed
Lines changed: 264 additions & 98 deletions
File tree
- app/components/UI/Predict
- components
- PredictGameDetailsContent
- PredictMarketOutcome
- hooks
- providers/polymarket
- views/PredictMarketDetails
- hooks
Lines changed: 10 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
| 15 | + | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
40 | | - | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
41 | 43 | | |
42 | 44 | | |
43 | 45 | | |
| |||
231 | 233 | | |
232 | 234 | | |
233 | 235 | | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
234 | 242 | | |
Lines changed: 7 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
53 | | - | |
| 53 | + | |
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| |||
221 | 221 | | |
222 | 222 | | |
223 | 223 | | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
224 | 229 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
77 | 81 | | |
78 | 82 | | |
79 | 83 | | |
| |||
95 | 99 | | |
96 | 100 | | |
97 | 101 | | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
98 | 120 | | |
99 | 121 | | |
100 | 122 | | |
101 | 123 | | |
102 | 124 | | |
| 125 | + | |
103 | 126 | | |
104 | 127 | | |
105 | 128 | | |
| |||
125 | 148 | | |
126 | 149 | | |
127 | 150 | | |
| 151 | + | |
128 | 152 | | |
129 | 153 | | |
130 | 154 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | | - | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
66 | 69 | | |
67 | 70 | | |
68 | 71 | | |
| |||
Lines changed: 4 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2268 | 2268 | | |
2269 | 2269 | | |
2270 | 2270 | | |
| 2271 | + | |
| 2272 | + | |
| 2273 | + | |
2271 | 2274 | | |
2272 | 2275 | | |
2273 | 2276 | | |
| |||
2311 | 2314 | | |
2312 | 2315 | | |
2313 | 2316 | | |
2314 | | - | |
| 2317 | + | |
2315 | 2318 | | |
2316 | 2319 | | |
2317 | 2320 | | |
| |||
Lines changed: 93 additions & 28 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
90 | 91 | | |
91 | 92 | | |
92 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
93 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
94 | 104 | | |
95 | 105 | | |
96 | 106 | | |
| |||
385 | 395 | | |
386 | 396 | | |
387 | 397 | | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
388 | 402 | | |
389 | 403 | | |
390 | 404 | | |
| |||
425 | 439 | | |
426 | 440 | | |
427 | 441 | | |
| 442 | + | |
428 | 443 | | |
429 | 444 | | |
430 | 445 | | |
| |||
580 | 595 | | |
581 | 596 | | |
582 | 597 | | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
583 | 666 | | |
584 | 667 | | |
585 | 668 | | |
| |||
737 | 820 | | |
738 | 821 | | |
739 | 822 | | |
| 823 | + | |
740 | 824 | | |
741 | 825 | | |
742 | | - | |
743 | | - | |
744 | | - | |
745 | | - | |
746 | | - | |
747 | | - | |
748 | | - | |
749 | | - | |
750 | | - | |
751 | | - | |
752 | | - | |
753 | | - | |
754 | | - | |
755 | | - | |
756 | | - | |
757 | | - | |
758 | | - | |
759 | | - | |
760 | | - | |
761 | | - | |
762 | | - | |
763 | | - | |
764 | | - | |
765 | | - | |
766 | | - | |
767 | | - | |
768 | | - | |
769 | | - | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
770 | 829 | | |
771 | 830 | | |
772 | 831 | | |
| |||
970 | 1029 | | |
971 | 1030 | | |
972 | 1031 | | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
973 | 1037 | | |
974 | 1038 | | |
975 | 1039 | | |
| |||
1357 | 1421 | | |
1358 | 1422 | | |
1359 | 1423 | | |
| 1424 | + | |
1360 | 1425 | | |
1361 | 1426 | | |
1362 | 1427 | | |
| |||
0 commit comments