Translated from: https://juejin.cn/post/7000631869628743688
In this context, “cross app” refers to the ability to share code and software modules across different executables on different platforms. It’s an advanced version of cross-platform development.
** Author: Bytedance Front End Platform Team - 熊文源**
The React Native based cross-app architecture enhances the delivery speed. However, problems arise in different game runtime environments when it scales. This is expected due to the complexity involved in the use case of RN in games. The key challenges are immersive experience, bootstrap latency, memory footprint, and rendering speed. These are known issues to React Native, hence we started optimization case-by-case to address them.
We test with a large volume of data in preparing for the actual optimization work. The React Native performance is good in ordinary apps. However, in games where low memory and highly saturated CPU are the norms, the issue of bootstrap latency becomes very notable. Let’s understand first the steps that are time consuming.
The bootstrap of React Native enlists 1) load the Core Bridge which encapsulates runtime, UI, and API components; 2) execute the domain logic in JavaScript and render the React components; 3) render the native UI elements in accordance with the components. Preloading of Core Bridge is a common tackle to improve bootstrap speed.
ReactInstanceManager
with the preloaded bundle. We load the instance directly from memory and bind it with rootview
when the respective page is invoked. This optimisation enhances the bootstrap speed by 30% - 50%. In games, we achieve <1s bootstrap in physical device, and <2s in emulators. Nonetheless, this particular method of “time–memory trade-off” is not scalable because space complexity is O(n) where n is the number of bundles.ReactInstanceManager
, and only load business package on demanded. It gives a 15% - 20% enhancement (react-native-multibundler).rootview
(with common package). Presumably this approach consumes more memory than preloading of just bridge and it achieves almost 0 TTI.All of the aforementioned approaches utilize memory to enhance latency, and they can all be feature toggled from the server side. Additionally, it is worth noting the following heuristic related to bootstrap time:
Fresco
.In addition to the aforementioned approaches, replacing JSC with Hermes can yield significant improvements in bootstrap performance. Detailed discussions on Hermes will be provided in upcoming posts.
The above heuristics that target bootstrap, are common to industry. The complex runtime of games has strict demands on memory consumption. This is because games generally consume more memory than ordinary apps.
Rendering performance plays a vital role in games. Due to the constrained runtime of games, characterized by high CPU load, React Native pages tend to be less performant in comparison to native-powered pages with the same level of layout complexity. To address this, following we list the critical points for React Native rendering optimisation that ensures support for consistent 60 FPS performance in the majority of cases.
Another crucial aspect to consider is hardware acceleration. React Native leverages native UI rendering, which delivers optimal performance when hardware acceleration is enabled. However, in most games, hardware acceleration is disabled due to the utilization of customized rendering modules or engines. Consequently, the FPS (frames per second) and UI responsiveness often fall below the expected quality bar, particularly in emulator (FPS 30). How did we improve the performance in such setting?