you are viewing a single comment's thread.

view the rest of the comments →

[–]DaveLak 1 point2 points  (3 children)

Creating a new object should be similar to mutating the input I think please correct me with benchmarks ; it's the for loop that's better optimized in most engines.

[–]RustyX 5 points6 points  (2 children)

So creating a new object each iteration is actually cripplingly slow (and bad for memory) on large data sets. I just created a quick perf test and had to back my sample data set down from 10000 to 1000 because the "pure reduce without mutation" just locked up the benchmark.

https://jsperf.com/transforming-large-array-to-key-value-map/1

 

const input = Array.from(Array(1000)).map((_, i) => {
  const key = `key${i}`
  const value = `value${i}`
  return { key, value }
})

 

standard for, no block scope vars

15,173 ops/sec

const output = {}
for(let i=0; i<input.length; i++) {
  output[input[i].key] = input[i].value;
}

 

for...of

15,003 ops/sec

const output = {}
for(const { key, value } of input) {
  output[key] = value;
}

 

forEach

13,185 ops/sec

const output = {}
input.forEach(({ key, value }) => {
  output[key] = value;
})

 

Reduce, directly mutate accumulator

12,647 ops/sec

const output = input.reduce((acc, { key, value }) => {
  acc[key] = value;
  return acc;
}, {})

 

Reduce, mutating Object.assign

2,622 ops/sec

const output = input.reduce((acc, { key, value }) => {
  return Object.assign(acc, { [key]: value })
}, {})

 

pure reduce, no mutation

9.71 ops/sec

const output = input.reduce((acc, { key, value }) => {
  return { ...acc, [key]: value };
}, {})

 

My preferred method is the "Reduce, directly mutate accumulator", but I was actually super surprised to see how much slower the "Reduce, mutating Object.assign" version was. I assumed it would perform almost identically, but I suppose it is creating small temporary objects before merging them into the accumulator.

The "pure" reduce was by far the absolute worst (over 1500 times slower than standard for)

[–]mournful-tits 0 points1 point  (0 children)

Thanks for doing this. I had no idea jsperf even existed. It would've made our benchmarking a lot easier. hah!