TypedArray access with many class instances vs pool

Benchmark created on


Setup

const capacity = 50_000_000

Test runner

Ready to run.

Testing in
TestOps/sec
Many class instances
class Foo {
  index = 0;
  #pool;
  constructor(pool, index) {
    this.index = index;
    this.#pool = pool;
  }
  get()          { return this.#pool._data[this.index]; }
  set(val)       { this.#pool._data[this.index] = val; }
}

class ClassPoolMemoryManager {
  constructor(capacity) {
    // contiguous backing store
    this._data = new Float64Array(capacity);

    // build object pool once
    this._free = new Array(capacity);
    for (let i = 0; i < capacity; ++i) {
      const foo = new Foo(this, i);
      this._free[i] = foo;          // every slot starts free
    }
  }

  /** Get a free Foo instance or `null` if exhausted */
  alloc() {
    const free = this._free.pop()
    // free.i = this.capacity - this._free.length
    return free
  }

  /** Return a Foo instance to the pool */
  free(foo) {
    this._free.push(foo);
  }
}

const classPool = new ClassPoolMemoryManager(capacity);
const foos = new Array(capacity);

console.time("class-pool alloc");
for (let i = 0; i < capacity; ++i) foos[i] = classPool.alloc();
console.timeEnd("class-pool alloc");

console.time("class-pool write");
for (let i = 0; i < capacity; ++i) foos[i].set(i);
console.timeEnd("class-pool write");

console.time("class-pool read");
let sumA = 0;
for (let i = 0; i < capacity; ++i) sumA += foos[i].get();
console.timeEnd("class-pool read");

ready
Pool
class TypedArrayMemoryManager {
  constructor(capacity) {
    this._data = new Float64Array(capacity);
    this._free = Array.from({ length: capacity }, (_, i) => i);
  }
  alloc()              { return this._free.length ? this._free.pop() : -1; }
  get(index)           { return this._data[index]; }
  set(index, val)      { this._data[index] = val; }
  free(index)          { this._free.push(index); }
}

const typedPool = new TypedArrayMemoryManager(capacity);
const idx = new Uint32Array(capacity);

console.time("typed-array alloc");
for (let i = 0; i < capacity; ++i) idx[i] = typedPool.alloc();
console.timeEnd("typed-array alloc");

console.time("typed-array write");
for (let i = 0; i < capacity; ++i) typedPool.set(idx[i], i);
console.timeEnd("typed-array write");

console.time("typed-array read");
let sumB = 0;
for (let i = 0; i < capacity; ++i) sumB += typedPool.get(idx[i]);
console.timeEnd("typed-array read");
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.