Performance: Immutable.js Map vs List vs plain JS Performance: Immutable.js Map vs List vs plain JS javascript javascript

Performance: Immutable.js Map vs List vs plain JS


The short answer is that the representation of data structures used by Immutable.js requires a lot of additional overhead to iterate through the elements of a List, compared to a native JS array.

Benchmarking Immutable.List.find and Array.find

Your benchmark is good, but we can simplify matters a bit by getting rid of the nested map; you're right to consider performance for realistic problems, but it can be helpful in understanding performance differences to simplify the problem as much as possible. It's also often useful in benchmarking to consider how performance changes over different input sizes. For instance, it's possible that in Immutable.js, List.prototype.find is implemented in such a way that the intitial call and setup take awhile but that the subsequent iterating through the List performs similarly to native JS Arrays; in this case, the difference in performance between native JS Arrays and Immutable.js lists would decrease for long input lengths (this turns out not to be the case).

Let's also create our own find function for native JS arrays, Array.prototype.ourFind to compare to the native Array.prototype.find to determine if the difference could in part be due to the performance of JS functions themselves vs. performance of functions built-in to the implementation.

Array.prototype.ourFind = function(predicate) {  for (let i = 0; i < this.length; i++) {    if (predicate(this[i])) return this[i];  }}function arrayRange(len) {  return new Array(len).fill(null).map((_, i) => i);}function immutListRange(len) {  return Immutable.fromJS(arrayRange(len));}function timeFind(coll, find, iters) {  let startTime = performance.now();  for (let i = 0; i < iters; i++) {    let searchVal = i % coll.length,      result = find.call(coll, item => item === searchVal);  }  return Math.floor(performance.now() - startTime);}const MIN_LEN = 10,  MAX_LEN = 1e4,  ITERS = 1e5;console.log('\t\tArray.find\tArray.ourFind\tList.find');for (let len = MIN_LEN; len <= MAX_LEN; len *= 10) {  console.log(`${len}\t\t\t` +    `${timeFind(arrayRange(len), Array.prototype.find, ITERS)}\t\t\t` +    `${timeFind(arrayRange(len), Array.prototype.ourFind, ITERS)}\t\t\t` +    `${timeFind(immutListRange(len), Immutable.List.prototype.find, ITERS)}`)}
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>