When Cheap Operations Aren't Cheap at Scale in Apps
A developer shares how real-time stock price updates at 30 packets per second froze the UI and how background threads fixed it.

Stock photo for illustration only, not from the actual event
- Streaming all price levels via WebSockets caused UI freezes during peak hours.
- Diffable Data Source failed because data arrived as full lists rather than snapshots.
- Computed properties choked the main thread under high frequency loads.
- Moving calculations to background threads successfully restored smooth scrolling.
During my time in my previous company, I learned valuable lessons about performance scaling, particularly that new APIs aren't always the right fit and operations considered cheap can become expensive at scale. This challenge began when I was tasked with handling real-time data using WebSockets. On paper, the feature seemed straightforward: instead of stopping at 10 price levels, the application needed to display all of them, which ranged anywhere between 80 to 137 price levels depending on the specific stock.
During peak hours, the previously responsive view suddenly froze, preventing users from scrolling up and down. Unfortunately, this issue manifested exclusively during peak trading hours, allowing it to slip past the QA process. I initially believed that implementing a Diffable Data Source based on UUID-associated data would resolve the bottleneck, but it only exacerbated the situation.

Stock photo for illustration only, not from the actual event
The core issue stemmed from the incoming data payload, which transmitted the entire list of price levels rather than a snapshot of incremental changes. Diffing the entire list repeatedly introduced pure overhead without any partial updates to optimize. In this specific scenario, utilizing tableView.reloadData() proved to be significantly faster, prompting me to fire up the profiler to uncover the true system bottleneck.
A deep dive into the profiler results revealed surprising culprits. Computed properties—such as color calculations for price movements and number formatting—were clogging the main thread. While these computations were cheap individually, encountering 30 packages per second, each containing every price level, transformed them into severe performance blockers. Even standard localization tasks contributed to freezing the main thread.
"The computations were cheap, but when hit with 30 packages per second, each carrying all price levels, they weren't cheap anymore."
Software Developer
In modern software engineering, high-frequency data streams often expose hidden inefficiencies in UI rendering pipelines. Operations that take mere microseconds become detrimental bottlenecks when multiplied across hundreds of data points and dozens of ticks per second. Decoupling business logic and formatting tasks from the main execution thread is a foundational practice for maintaining responsive user interfaces in data-heavy applications.
The remediation strategy proved straightforward: eliminate all calculations inside computed properties. Instead, all properties are calculated on background threads during the conversion of WebSocket responses into view data, rendering the UI layer passive as it simply reads pre-computed values. Following these optimizations, the application successfully sustained peak trading hours with fluid scrolling, establishing a clear protocol for diagnosing performance degradation moving forward.
Source: Dev.to
Found something wrong in this article? Report an issue with this article
Comments
Leave a Comment