0

I have a question in performance. Assume I have a massive array of objects called records. My goal is to create a Set (which makes sure that I have distinct values) that contains the value value of records from records that meet a certain condition - if(rec.otherValue === 'something specific'). I have two possible ways that will yield the desired result:

Option 1:

const set = new Set();
records.foreach(rec => {
   if(rec.otherValue === 'something specific'){
       set.add(rec.value);
   }
});

First option is straight-forward. I go through all records and add the desired value to the Set if the specific condition is met.

Option 2:

const set = new Set();
const filteredRecords = records.filter(rec => rec.otherValue === 'something specific');
filteredRecords.foreach(rec => {
   set.add(rec.value);
});

Second option first filters the massive records array in order to get a much more specific array of objects (from hundreds of records to less than 10), and then addidng the desired values to the Set.

Both options yield the exact same result. My question is: which one is the best performance-wise? My goal is to make the function as fast as possible. And if there's a third, even faster option, please do share.

  • Have you heard about big O notation? In your case, the complexity is always O(n). And the performance is the same. First way makes it more readable :) Please check here https://stackoverflow.com/questions/16917958/how-does-if-affect-complexity – hurricane Apr 06 '21 at 19:06
  • @hurricane yes, I'm well aware of the O notation and I'm also aware it will give me a time complexity of O(n). But that my question isn't about time complexity - it's about performance. I'm certain that the developers of js developed both functions in the best ways regarding performance. It doesn't mean that despite they have the same time complexity, they both have the same speed/performance/resource allocations – Gabriel Edery Apr 06 '21 at 19:09
  • `Which one is the best performance-wise?` They are equivalent since they have the same time complexity. The difference will be in nanoseconds. – hurricane Apr 06 '21 at 19:28

3 Answers3

0

And what about this? I think it is highly readable and that is far more important as just the performance.

const condition = val => val === 'something specific'
const set = new Set(records.filter(condition))
Vladislav Ladicky
  • 1,249
  • 1
  • 6
  • 9
0

If you want speed, Nothing beats native (vanilla) javascript when it comes to performance. Then,

for (var i=0; i< records.length; i++) {
// your operations
}

Please check : Why using for is faster than some() or filter()

and

https://web.archive.org/web/20170403221045/https://blogs.oracle.com/greimer/entry/best_way_to_code_a

vijayakm
  • 57
  • 4
0

Testing this
I was curious about just how much faster the modern methods are, so I set up some tests on JSPerf. Here’s what I found:

  • for loops and the forEach() method perform pretty close to each other.
  • Methods like map() and filter() are about twice as fast as using forEach() and pushing to a new array to do the same thing.
  • Using forEach() for multi-step manipulation is about twice as fast as chaining methods like filter() and map().
  • These results were consistent across Chrome, Firefox, and Safari. I was concerned that only the V8 JavaScript rendering engine had been optimized this way, but all modern browsers saw similar results.

Link to source
Benchmark for: reduce(), filter(), map(), forloop and forEach()

I tried running the benchmark multiple times and got the for loop as the slowest while forEach() and reduce() as the fastest.

There's another option you can use, with the use of reduce().

Here's an example:

let data = [
  {
    id: 1,
    value: 'one'
  }, {
    id: 2,
    value: 'two'
  }, {
    id: 3,
    value: 'three'
  }, {
    id: 4,
    value: 'four'
  }, {
    id: 5,
    value: 'five'
  },
];

// Filters IDs of odd numbers [1,3,5]
let new_arr = data.reduce((a, b) => {
  if ([1,3,5].includes(b.id)) {
    a.push(b.value);
  }
  return a;
}, []);
console.log(new_arr); // Expected Result: ['one', 'three', 'five']

// Or you can use this one Liner
let new_arr_1 = data.reduce((a, b) => a.concat(([1,3,5].includes(b.id) ? b.value: [])), []);
console.log(new_arr_1); // Expected Result: ['one', 'three', 'five']
Techuila
  • 1,112
  • 6
  • 12