In this blog post, I explain when you should avoid
Array.prototype.includes() and what you can use instead.
I ran into a performance issue on a recent project. After some debugging, I came across the following: There was an
Array with a large amount of data. To check if a certain value is included
Array.prototype.includes() was used. All this is not rocket science - or is it?
Let's start with a simple measurement. An array with a million entries and we check if certain values are included in the array.
const arr = [...Array(1000000).keys()]; arr.includes(1); // 0.077ms arr.includes(10): // 0.004ms arr.includes(100); // 0.003ms arr.includes(1000); // 0.003ms arr.includes(10000); // 0.014ms arr.includes(100000); // 0.113ms arr.includes(1000000); // 1.066ms
1000000 is not included in the array - the runtime is already 1 second. Optimizing this is probably still considered micro-optimization. If you use
Array.prototype.filter() in combination with
Array.prototype.includes() for large data sets, the snail will overtake you!
The reason for this is the time complexity.
Array.prototype.filter() has a linear complexity (
I found the following article that explains the Big O notation well:
Let's take a look at
Set.prototype.has() and compare the performance with
const arr = [...Array(1000000).keys()]; arr.includes(1000000); // 1.336ms
const arr = [...Array(1000000).keys()]; const setObj = new Set(arr) setObj.has(1000000); // 0.016ms
Two simple examples with very different runtimes -
Set.prototype.has() has a constant complexity (
Array.prototype.includes() has a linear complexity (
It makes no sense to replace
Set.prototype.has() everywhere, because it is not always faster. It's important to use functions with loops carefully. 😉
I performed a few benchmarks for this purpose, which you can see in the following table:
|1||836859994.45 ops/s ± 1.01%||176325072.58 ops/s ± 1.49%||
|10||826996638.6 ops/s ± 0.95%||87438374.47 ops/s ± 6.73%||
|100||800038628.18 ops/s ± 0.56%||143287118.03 ops/s ± 0.86%||
|1000||590640746.37 ops/s ± 0.63%||171114526.18 ops/s ± 0.7%||
|10000||96545.28 ops/s ± 1.06%||133468419.89 ops/s ± 1.69%||
|100000||9380.42 ops/s ± 0.96%||131819933.56 ops/s ± 0.82%||
If you have any kind of feedback, suggestions or ideas - feel free to comment this post!