React Native Memory profiling (JSC vs V8 vs Hermes)
Tags: reactnative, javascript, performance, memory
Published: 2019-07-22 08:08:47

##Problem
We were facing memory issue with our Android app **@WalmartLabs** since stock JSC was doing minimal garbage collection in Android. We tried lots of options to reduce the memory footprint of our app with no success.
Problem become severe with react native flat list with lots of items (~1k in our case). Memory kept on growing with each navigation between the screens and not coming down even after clearing the data

## Savior
A Few weeks back, @kudochien tweeted about [react-native-v8](https://www.npmjs.com/package/react-native-v8) package which can enable us to bundle V8 with react-native for android instead of JSC

{% twitter 1142104750436970496 %}

During the same time [jsc-android](https://www.npmjs.com/package/jsc-android/v/245459.0.0) also release a newer version 245459.0.0 and Hermes was announced during @ChainReactConf

So we decided to compare memory footprints of [Stock JSC (v241213.1.0)](https://www.npmjs.com/package/jsc-android/v/241213.1.0),  new [JSC(v245459.0.0)](https://www.npmjs.com/package/jsc-android/v/245459.0.0),  [Hermes](https://facebook.github.io/react-native/docs/hermes/) and [react-native-v8](https://www.npmjs.com/package/react-native-v8) and created a sample repository to mimic real world use case. {% github https://github.com/bhaskarGyan/react-native-memory-profile %} 
We considered below use cases.
1. Flat list with ~1k items
2. Huge array list to mimic storing/removing large record (one record was new Array(999999).join('--')) in react state
3. Memory footprint with [react-navigation](https://www.npmjs.com/package/react-navigation)

### ABI used -> x86_64

##Observations

###TL;DR
New JSC v241213.1.0 handle memory better than its previous version v241213.1.0, followed by Hermes but react-native-v8 beat them by a huge margin in app startup memory, handling memory of flat list, memory footprint of large data and most importantly Garbage collection

{% twitter 1146656548556439553 %}

###Sample APP
![Sample APP](https://pbs.twimg.com/media/D-m3YUFVUAIpRYW.jpg:small)

###Steps

* Home -> flat list
* Scroll till last item (870 items) -> Home
* Memory hungry Array -> add record (100) -> remove -> Home
* flat list -> Memory hungry Array -> add record (100) -> Home


###Stock JSC (v241213.1.0)
It was the worst performer among three. Memory footprint was very High and minimal Garbage collection

**App startup memory(MB)** - 59 (total), 20 (JS)
**After flat list loaded(MB) (870 items)** -> 239(Total),128 (JS)
**After adding records (app crashed after adding 16 records) (MB)** -> 1153(Total),1098(JS)
**Garbage collection** - minimal

#### Memory consumption graph
![Stock JSC](https://raw.githubusercontent.com/bhaskarGyan/react-native-memory-profile/master/MemoryProfilingResult/%20JSC_241213.1.0.png)

###New JSC (v245459.0.0)
It was better than Stock JSC in handling memory and Garbage collection.

**App startup memory(MB)** - 53 (total), 15 (JS) 
**After flat list loaded(MB) (870 items)** -> 191(Total),107 (JS)
**After adding records (MB)** -> 714(Total),596(JS)
**Garbage collection** -> Yes, memory came down to 234 MB (Total), 121 MB (JS)

#### Memory consumption graph
![New JSC (v245459.0.0)](https://raw.githubusercontent.com/bhaskarGyan/react-native-memory-profile/master/MemoryProfilingResult/%20JSC_245459.0.0.png)

###React-Native-V8

**App startup memory(MB)** - 40 (total), 9 (JS) [&darr; 55% (JS)]
**After flat list loaded(MB) (870 items)** -> 105(total), 36 (JS) [&darr; 70% (JS)]
**After adding records (100)** -> 82(total),25(JS) [GC ran in-between]
**Garbage collection** -> Yes,max memory reached 103 MB(total), 36 MB(JS) and after GC around 78 MB(total),14 MB(JS)

#### Memory consumption graph
![React-Native-V8](https://github.com/bhaskarGyan/react-native-memory-profile/blob/master/MemoryProfilingResult/V8.png?raw=true)


###Hermes
Hermes was announced @ChainReactConf on 11th July. It is an open-source JavaScript engine optimized for running React Native apps on Android.

**App startup memory(MB)** - 33 (total), 7 (JS) [&darr; 65% (JS)]
**After flat list loaded(MB) (870 items)** -> 397(total), 110 (JS)
**After GC (MB) ** -> 358 (total), 48 (JS)
**After adding records (app crashed after adding 50 records)** -> 556(total),149(JS) 
**Garbage collection** -> Yes,max memory reached 556 MB(total), 149 MB(JS) and after GC around 143 MB(total),48 MB(JS)

#### Memory consumption graph
![Hermes](https://raw.githubusercontent.com/bhaskarGyan/react-native-memory-profile/master/MemoryProfilingResult/Hermes.png)

##Conclusion:

Based on the memory profiling graph react-native-v8 is the winner closely followed by Hermes.

![V8vsJSCvsHermes](https://raw.githubusercontent.com/bhaskarGyan/react-native-memory-profile/master/MemoryProfilingResult/JSCvsV8vsHermes.png?raw=true)

But,there is no one silver bullet for choosing JS engine in react-native it all depends on ones use-case. It is very important to measure your app performance against different JS engine and go with the one which suites you the best.

It's good that now react-native is giving options to the user to choose JS engine based on the use case.