ES6 Set Performance in Chrome's V8 JavaScript Engine

One of the nice things that came with ES6 were native Sets, provided so that developers didn’t have to keep importing or rolling their own custom Set polyfills. As I was writing a post about the advantages of using an EnumSet over a generic Set, I coded up and included some performance examples which yielded some very surprising results.

It turns out that the Set implementation in Chrome’s V8 JavaScript Engine is very slow, about 2x slower than a Naive Set polyfill using a Map<String, Boolean>.

I have included the test below using the following Set implementations, compared to the native ES6 Set implementation.

class NaiveSet {
  constructor(){
    this.map = {};
  }

  add(el){
    this.map[el] = true;
  }

  has(el){
    return this.map[el] == true;
  }
}

class EnumSet {
  constructor(){
    this.array = [];
  }

  add(el){
    this.array[el] = true;
  }

  has(el){
    return this.array[el] == true;
  }
}

class BitEnumSet {
  constructor(){
    this.num = 0;
  }

  add(el){
    this.num = this.num | 1<<el;
  }

  has(el){
    return (this.num & 1<<el) != 0;
  }
}





The NaiveSet implementation represents the base polyfill that Sets in JavaScript are based on, mapping a String to a Boolean.

The EnumSet implementation was theoretically supposed to take advantage of the optimizations in the Array implementation for using only Integer keys, but it ended up no faster than the NaiveSet.

The BitEnumSet implementation was theoretically supposed to take advantage of the speed of bit manipulation, but it also appears no faster than the NaiveSet.