chakra-core / chakra-core/ChakraCore

High heap fragmentation caused by sparse arrays

Open
#5,261 1 comment 0 reactions 0 assignees View on GitHub
Memory
Dominant language
JavaScript
Stars
9.3k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

In react native apps there are usually 1-3K elements stored in the [instanceCache](https://github.com/facebook/react-native/blob/master/Libraries/Renderer/oss/ReactNativeRenderer-prod.js#L988) array. Pattern: declared as an object/dictionary, used as an array, frequent add/delete operations, indexes grow continuously (i.e. they are not random hash values). This causes Chakra to create a highly sparse array.

This array in snapshot 1 (note, that in JS it's an object, but Chakra represents it as an array):

```
1 2 ^ v > | 0x0000015b4bb56440 (level -1 ) = (??) (!jd.var) Chakra!Js::JavascriptArray
1 257 ^ v * | 0x0000015b50e6d020 (level 0 ) Js::JavascriptArray.{SparseArraySegments}

0:016> dt Js::SparseArraySegmentBase 0x0000015b50e6d020
Chakra!Js::SparseArraySegmentBase
+0x000 left : 0
+0x004 length : 0x80b
+0x008 size : 0xc7f
+0x010 next : (null)
```

Then the same array in snapshot 2, after a lot of activity in the UI (note, that the sparse array segment has been replaced):

```
1 2 ^ v > | 0x0000015b4bb56440 (level -1 ) = (??) (!jd.var) Chakra!Js::JavascriptArray
1 257 ^ v * | 0x0000015b5ba60020 (level 0 ) Js::JavascriptArray.{SparseArraySegments}

0:015> dt Js::SparseArraySegmentBase 0x0000015b5ba60020
Chakra!Js::SparseArraySegmentBase
+0x000 left : 0
+0x004 length : 0x857b
+0x008 size : 0xa0af
+0x010 next : (null)
```

The heap usage as reported by `!hbstats` was below 40%.

Defragmenting can be done on JS side with `instanceCache = {...instanceCache}`. This bumped the heap usage to 75% and packed the array size to a more reasonable value:

```
1 2 ^ v > | 0x00000226c5141b40 (level -1 ) = (??) (!jd.var) Chakra!Js::JavascriptArray
1 3345 ^ v * | 0x00000226d5347020 (level 0 ) Js::JavascriptArray.{SparseArraySegments}

0:011> !jd.var 0x00000226c5141b40
Js::JavascriptArray * 0x00000226c5141b40 (TypeIds_Array)
class Js::SparseArraySegmentBase * 0x00000226`d5347020
+0x000 left : 0
+0x004 length : 0xd1c
+0x008 size : 0x14d3
+0x010 next : (null)
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.