Array.protoype.indexOf() Performance Regression
tctacm opened this issue · comments
Bug Description
The Array.prototype.indexOf()
functions seems to be significantly slower on Hermes when compared to JSC. I first noticed the issue in React Native 0.64 inside the JSTimers file: https://github.com/facebook/react-native/blob/0645c38014e8310d8e387dabc860c8c5878beb6e/Libraries/Core/Timers/JSTimers.js#L62 , however, I have reproduced a case using the Hermes CLI to verify my findings.
- I have run
gradle clean
and confirmed this bug does not occur with JSC - The issue is reproducible with the latest version of React Native.
Hermes git revision (if applicable): release-v0.12? I'm using Hermes CLI with version 0.12.0
React Native version: N/A
OS: macOS Sonoma 14.2.1
Platform (most likely one of arm64-v8a, armeabi-v7a, x86, x86_64): x86_64
Steps To Reproduce
The following code running on Hermes will take significantly longer:
index_of_test.js
:
const ARR_SIZE = 10000;
// Make an array of ARR_SIZE increasing non-negative integers
// [0, 1, 2, 3, 4, 5, 6, 7, 8, ...]
var test_arr = [];
for (var i = 0; i < ARR_SIZE; i++) {
test_arr.push(i);
}
// Call indexOf 1000 times with the last element in the array
var start = Date.now();
for (var i = 0; i < 1000; i++) {
test_arr.indexOf(ARR_SIZE - 1);
}
var end = Date.now();
print('Array.indexOf last element time: ' + (end - start));
// Call indexOf 1000 times with the first element in the array
var start = Date.now();
for (var i = 0; i < 1000; i++) {
test_arr.indexOf(0);
}
var end = Date.now();
print('Array.indexOf first element time: ' + (end - start));
- Run with hermes cli:
hermes ./index_of_test.js
Array.indexOf last element time: 253
Array.indexOf first element time: 0
- Run with JSC cli:
jsc --useJIT=false ./index_of_test.js
Array.indexOf last element time: 3
Array.indexOf first element time: 0
My example seems to indicate that Hermes is much slower at iterating through and comparing Array values when compared to JSC.
Funnily enough, the same test using Array.prototype.includes()
has similar performance between Hermes and JSC. I would assume (probably incorrectly) that the two functions use a similar algorithm. Although in this case, JSC is also much slower compared to its indexOf
performance.
- Run with
hermes ~/includes_test.js
Array.includes last element time: 122
Array.includes first element time: 0
- Run with
jsc --useJIT=false ~/includes_test.js
Array.includes last element time: 116
Array.includes first element time: 0
The Expected Behavior
Hermes performance on Array.protoype.indexOf()
should be on-par with JSC performance.
Thank you for reporting this! We can reproduce it and will address it. This is most likely because Array.protoype.indexOf()
doesn't have a fast-path checking for an array.