chakra-core / chakra-core/ChakraCore
High heap fragmentation caused by sparse arrays
- 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
Assessment
This issue has not been assessed yet.