Last active
October 25, 2023 23:46
-
-
Save robbiespeed/7e5d56ed2b58e8933449445c9e4424c4 to your computer and use it in GitHub Desktop.
JS Benches
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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