Discord is a patented freeware Voice Over IP (VoIP) application and digital distribution platform designed for video gaming communities, that specializes in text, image, video and audio communication between users in a chat channel. Discord uses the metaphors of servers and channels similar to Internet Relay Chat even though these servers do not map to traditional hardware or virtual servers due to its distributed nature. A user can create a server on Discord, managing its public visibility and access, and create one or more channels within this service. Within a server, depending on access controls, users can create channels within a category framework, with the visibility and access on the channels also customizable to the server.
Developing mobile with React Native is convenient when building applications on different platforms without having to completely re-code. Most companies developing mobile on the current native stacks find that they must compromise in some way. Either on productivity (develop the same product multiple times with different engineers on different stacks), on quality (make low-quality apps) or on a scope (focus on a single platform). The path towards stopping these compromises is inventing new mobile stacks — like React Native. To build its iOS app from the core of React app, Discord adopted React Native as soon as it became an open sourced.
Once the App started to display signs indicating that it is degrading across several vectors (frame drops, battery drain, time to interaction, etc.) the developers decided on getting to the root of the problem and tackle it. With this in mind, a mobile performance squad, was created whose mission was to execute a deep dive into driving top tier performance on across all supported iOS devices.
The following changes were made:
- Phase 1: Flux Store Optimisations
Every action that triggered an update to the user store which holds the state of all known users resulted in a 30ms emit. The message load/cache restore actions which directly result in processing and rendering chat messages resulted in a 500ms on an iPhone XS and 1000mson iPhone 6s.
- Phase 2: React Component Optimizations
React commits could cost up to 200ms when affecting things at the higher levels of the component tree. On top of this, Discord was going through up to three commit passes when the app was starting up. A change was made so that its stores could initialize with the correct data, avoiding multiple commit passes and even shrinking the view hierarchy.
- Phase 3: Main Thread Optimizations
Once the Flux stores were performing well, it was discovered that the emoji picker itself was the source of the UI lockup. To address this logging was added to every ancestor component of emoji picker and it was found that the chat input component was remounting when switching between private messages and servers. Merging the two components reduced the 2s lockup down to 500ms, which was a win.
The final problem to tackle was that using Discord for a bit could result in the battery heating up. It was understood upon investigation that the main UI thread would sit at 10% CPU when looking at a Discord server; it always had a spinning animation in the background chewing away at CPU.
Phase 4: Perceived Performance Optimizations
One of the primary interactions with Discord involves the left and right drawers. The component that powers them was created the week that React Native was released in 2015, and still suffered from the shortcomings of those times. The other problem with the drawers was that they depended on React Native JS Responder system which works well in most cases, but not when there are gestures and scroll views involved. This was solved using ‘react-native-reanimated’.
Phase 5: RAM Bundles
All these steps strung together made for a stable and usable Discord App with Native iOS performance using React Native.