Boost Android performance using Hermes

Divyanshu Maithani
Instawork Engineering
5 min readDec 2, 2020

--

At Instawork, we’ve been using React Native for our mobile apps. React Native by default doesn’t perform as well in Android as it does in iOS. In this post I’ll cover how we improved the performance of Instawork Gigs and Jobs app using the new Hermes JavaScript engine.

Architecture

A large portion of Instawork’s app is written in JavaScript. The application code which includes screens, components, services, Redux (saga) modules runs on JavaScript. We are using several native libraries from the community and a few of our own wherever we need native functionality.

Since the app was built in React Native from the ground up it works well for us.

  • Faster development since we don’t have to deal with native code for most features
  • Leaner team size since a major chunk of code is in JavaScript
  • Same API as React, learn once, write anywhere

Background

Before shipping the Hermes engine we were running React Native 0.59. This was working well for us but we were running into performance issues on Android, especially for low-to-mid range devices. Refer to the chart below.

Average startup time comparison between iOS and Android

The average Time to Interactive (TTI) (startup time) for iOS was 1–1.5s. For Android the average was hitting 5–6s. Since a lot of our users are using (low to mid range) Android devices it was a big motivation for us to bring this number down.

Fortunately for us, the React Native team rolled out the Hermes engine some time back.

Hermes engine

Hermes is a JavaScript engine optimized for running React Native apps on Android.

Traditionally, React Native apps use JavaScript Core (JSC) as the default JavaScript engine. On iOS it uses the existing JSC that powers Safari. On Android, JSC is shipped with the application. Therefore, by default, React Native apps run better on iOS (since JSC is optimized for iOS).

Switching to the Hermes engine swaps out JSC for Hermes on Android apps. It promises:

  • Faster app launch: thanks to build-time pre-compilation of JavaScript into efficient bytecode.
  • Leaner app: Hermes is small in APK size, lean on memory, and starts instantly. This, in turn, reduces APK size, memory footprint and start up time for your apps on Android.
  • Easy integration: simple to integrate (3 lines of code).

Rolling out Hermes engine

The biggest challenge for us in order to rollout Hermes engine was to upgrade our apps from React Native v0.59 to v0.61 (since Hermes requires at least React Native v0.60.4).

Upgrading React Native

A lot of modules were removed from React Native core to make it leaner. This meant fixing quite a bit of old code and installing new native libraries for deprecated and removed modules.

React Native now uses autolinking which meant upgrading a lot of native dependencies and fixing the configurations, podfiles, gradle, etc. Some modules had breaking changes so we had to fix some application code to use the newer APIs. A few modules had too many breaking changes to fix along with upgrading React Native, these were not updated and linked manually.

Like with each React Native upgrade there were quite a bit of new linting and Flow errors which were fixed as well.

Quite a bit of our unit and integration tests also failed, which needed to be fixed.

After upgrading React Native and fixing the build our CI needed extra fixes.

Thanks to the upgrade helper tool, our experience with past upgrades and lot of amazing work from the team we were able to successfully upgrade our app to React Native v0.61.4.

Rolling out React Native 0.61

Before shipping Hermes engine we wanted to ensure that our app was running without any issues. We first rolled out the app running React Native 0.61 without Hermes engine to catch regressions if any. We did a phased roll out over 7 days while monitoring error logs on Sentry, play store and app store.

After ensuring things were working smoothly on React Native v0.61, it was time to ship the Hermes engine.

Rolling out Hermes

We started the rollout for Hermes engine in a similar phased manner over 7 days while monitoring error logs, performance metrics and crashes on Play store.

Tracking app startup TTI at 25% rollout (startup time drops from 6s to nearly 2s)

Performance improvements and other metrics

The results from this upgrade have been pretty good. Checkout the following video showcasing reduction in app startup time:

Startup time comparison of the app before and after Hermes engine upgrade

Gathering metrics

A couple of useful commands for gathering these commands involve using adb. It’s a good idea to run this on a real device (Browserstack also provides these if you don’t have an Android device handy). For a physically connected device, you should have USB debugging enabled.

We’re using the following commands to measure CPU and memory usage respectively:

adb shell dumpsys gfxinfo com.instaworkmobile.beta
adb shell dumpsys meminfo com.instaworkmobile.beta

Here com.instaworkmobile.beta is the package name.

For detailed metrics refer to this gist.

Memory footprint

We noticed a reduction in memory usage. The following screenshots displays the max memory usage by the app for the login flow, running on a 4 year old Android device.

Before upgrade — login flow — max memory at 206 MB
After upgrade — login flow — max memory at 141 MB

APK and installation size

With the Hermes engine the APK size for our app reduced from 28.6 MB to 19.8 MB.

The installation size also dropped quite a bit. On a One Plus 6 device (running Android 10) this dropped from 64.86 MB to 46.85 MB for a fresh app install:

Before upgrade — installation size 64.86 MB
After upgrade — installation size 46.85 MB

Automation — Browserstack integration

We’ve also integrated capturing metrics for CPU and memory usage into our QA process, specifically on Browserstack. This lets us monitor different flows in the app for performance regressions.

These are generated from the dumpsys commands mentioned above.

Capturing CPU and memory usage in our automation suite

Conclusion

If you’re looking for a quick way to boost performance for your React Native app on Android, we highly recommend trying out the Hermes engine.

The most tedious part of this would be upgrading your app’s React Native version (especially if you were using a version prior to v0.60). Once you’re on at least React Native v0.60.4, swapping out the JavaScript engine to Hermes should be only a few lines of code change.

Special thanks to our team for their amazing work, especially Florent, Ashwini, Rahul and Arpit.

--

--