Skip to content

Instantly share code, notes, and snippets.

@robbiespeed
Last active October 25, 2023 23:46
Show Gist options
  • Save robbiespeed/7e5d56ed2b58e8933449445c9e4424c4 to your computer and use it in GitHub Desktop.
Save robbiespeed/7e5d56ed2b58e8933449445c9e4424c4 to your computer and use it in GitHub Desktop.
JS Benches
import { bench, run } from 'mitata';
// This is a benchmark of the performance impact of using private properties.
const nCount = 1000;
const iCount = 1000;
class FooN {
#state = 1;
#inc = 13;
get state() {
return this.#state;
}
set state(v) {
this.#state = v;
}
get inc() {
return this.#inc;
}
set inc(v) {
this.#inc = v;
}
}
bench('NativePrivates', () => {
let i = iCount;
while (i-- > 0) {
const foo = new FooN();
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
}
}
});
class FooC {
_state = 1;
_inc = 13;
get state() {
return this._state;
}
set state(v) {
this._state = v;
}
get inc() {
return this._inc;
}
set inc(v) {
this._inc = v;
}
}
bench('ConventionalPrivates', () => {
let i = iCount;
while (i-- > 0) {
const foo = new FooC();
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
}
}
});
class FooCNF {
constructor() {
this._state = 1;
this._inc = 13;
}
get state() {
return this._state;
}
set state(v) {
this._state = v;
}
get inc() {
return this._inc;
}
set inc(v) {
this._inc = v;
}
}
bench('ConventionalPrivates (No fields)', () => {
let i = iCount;
while (i-- > 0) {
const foo = new FooCNF();
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
}
}
});
const FooProto = {
get state() {
return this._state;
},
set state(v) {
this._state = v;
},
get inc() {
return this._inc;
},
set inc(v) {
this._inc = v;
},
};
bench('ConventionalPrivates (__proto__ last prop)', () => {
let i = iCount;
while (i-- > 0) {
const foo = {
_state: 1,
_inc: 13,
__proto__: FooProto,
};
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
}
}
});
const FooProtoB = {
get state() {
return this._state;
},
set state(v) {
this._state = v;
},
get inc() {
return this._inc;
},
set inc(v) {
this._inc = v;
},
};
bench('ConventionalPrivates (Object.create)', () => {
let i = iCount;
while (i-- > 0) {
const foo = Object.create(FooProtoB);
foo._state = 1;
foo._inc = 13;
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
}
}
});
const FooProtoC = {
get state() {
return this._state;
},
set state(v) {
this._state = v;
},
get inc() {
return this._inc;
},
set inc(v) {
this._inc = v;
},
};
bench('ConventionalPrivates (__proto__ first prop)', () => {
let i = iCount;
while (i-- > 0) {
const foo = {
__proto__: FooProtoC,
_state: 1,
_inc: 13,
};
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
}
}
});
bench('ConventionalPrivates (Local get/set)', () => {
let i = iCount;
while (i-- > 0) {
const foo = {
_state: 1,
_inc: 13,
get state() {
return this._state;
},
set state(v) {
this._state = v;
},
get inc() {
return this._inc;
},
set inc(v) {
this._inc = v;
},
};
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
}
}
});
await run();
import { bench, run } from 'mitata';
// This is a benchmark of the performance impact of using private properties.
const nCount = 1000;
const iCount = 1000;
function runLoop(foo, dynamicKey) {
let n = nCount;
while (n-- > 0) {
foo.state += foo.inc;
foo[dynamicKey] = foo[dynamicKey] + 1;
}
return n;
}
function defineGetSet(object, key, getter, setter) {
Object.defineProperty(object, key, {
get: getter,
set: setter,
// To most closely match declared getter/setters
configurable: true,
});
}
class FooN {
#state = 1;
#inc = 13;
get state() {
return this.#state;
}
set state(v) {
this.#state = v;
}
get inc() {
return this.#inc;
}
set inc(v) {
this.#inc = v;
}
}
bench('NativePrivates', () => {
let i = iCount;
while (i-- > 0) {
const foo = new FooN();
const dynamicKey = `k${i}`;
let dyn = 0;
defineGetSet(
foo,
dynamicKey,
() => dyn,
(v) => {
dyn = v;
}
);
runLoop(foo, dynamicKey);
}
});
class FooC {
_state = 1;
_inc = 13;
get state() {
return this._state;
}
set state(v) {
this._state = v;
}
get inc() {
return this._inc;
}
set inc(v) {
this._inc = v;
}
}
bench('ConventionalPrivates', () => {
let i = iCount;
while (i-- > 0) {
const foo = new FooCNF();
const dynamicKey = `k${i}`;
let dyn = 0;
defineGetSet(
foo,
dynamicKey,
() => dyn,
(v) => {
dyn = v;
}
);
runLoop(foo, dynamicKey);
}
});
class FooCNF {
constructor() {
this._state = 1;
this._inc = 13;
}
get state() {
return this._state;
}
set state(v) {
this._state = v;
}
get inc() {
return this._inc;
}
set inc(v) {
this._inc = v;
}
}
bench('ConventionalPrivates (No fields)', () => {
let i = iCount;
while (i-- > 0) {
const foo = new FooCNF();
const dynamicKey = `k${i}`;
let dyn = 0;
defineGetSet(
foo,
dynamicKey,
() => dyn,
(v) => {
dyn = v;
}
);
runLoop(foo, dynamicKey);
}
});
const FooProto = {
get state() {
return this._state;
},
set state(v) {
this._state = v;
},
get inc() {
return this._inc;
},
set inc(v) {
this._inc = v;
},
};
bench('ConventionalPrivates (__proto__)', () => {
let i = iCount;
while (i-- > 0) {
const dynamicKey = `k${i}`;
let dyn = 0;
const foo = {
_state: 1,
_inc: 13,
get [dynamicKey]() {
return dyn;
},
set [dynamicKey](v) {
dyn = v;
},
__proto__: FooProto,
};
runLoop(foo, dynamicKey);
}
});
const FooProtoB = {
get state() {
return this._state;
},
set state(v) {
this._state = v;
},
get inc() {
return this._inc;
},
set inc(v) {
this._inc = v;
},
};
bench('ConventionalPrivates (Object.create)', () => {
let i = iCount;
while (i-- > 0) {
const foo = Object.create(FooProtoB);
const dynamicKey = `k${i}`;
let dyn = 0;
defineGetSet(
foo,
dynamicKey,
() => dyn,
(v) => {
dyn = v;
}
);
runLoop(foo, dynamicKey);
}
});
bench('ConventionalPrivates (Local get/set)', () => {
let i = iCount;
while (i-- > 0) {
const dynamicKey = `k${i}`;
let dyn = 0;
const foo = {
_state: 1,
_inc: 13,
get state() {
return this._state;
},
set state(v) {
this._state = v;
},
get inc() {
return this._inc;
},
set inc(v) {
this._inc = v;
},
get [dynamicKey]() {
return dyn;
},
set [dynamicKey](v) {
dyn = v;
},
};
runLoop(foo, dynamicKey);
}
});
await run();
import { bench, run } from 'mitata';
// This is a benchmark of the performance impact of using private properties.
const nCount = 10;
const iCount = 1000000;
class FooN {
#state = 1;
#inc = 13;
run() {
let n = nCount;
while (n-- > 0) {
this.#state += this.#inc;
}
return n;
}
}
bench('NativePrivates', () => {
let i = iCount;
while (i-- > 0) {
new FooN().run();
}
});
class FooC {
_state = 1;
_inc = 13;
run() {
let n = nCount;
while (n-- > 0) {
this._state += this._inc;
}
return n;
}
}
bench('ConventionalPrivates', () => {
let i = iCount;
while (i-- > 0) {
new FooC().run();
}
});
const FooNCProto = {
run() {
let n = nCount;
while (n-- > 0) {
this._state += this._inc;
}
return n;
},
};
bench('ConventionalPrivates (No Class)', () => {
let i = iCount;
while (i-- > 0) {
const foo = {
_state: 1,
_inc: 13,
__proto__: FooNCProto,
};
foo.run();
}
});
await run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment