Last active
July 6, 2021 02:21
-
-
Save noseratio/aeabb3fb4afecd4e4e17875b0da8aa45 to your computer and use it in GitHub Desktop.
Timing various Deferred implementations
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
void async function() { | |
// DeferredAsClass | |
class DeferredAsClass { | |
resolve; | |
reject; | |
promise = new Promise((s, f) => { this.resolve = s; this.reject = f; }); | |
} | |
// DeferredAsClassWithConstructor | |
class DeferredAsClassWithConstructor { | |
resolve; | |
reject; | |
promise; | |
constructor() { | |
this.promise = new Promise((s, f) => { this.resolve = s; this.reject = f; }); | |
} | |
} | |
// DeferredAsDerivedClass | |
class DeferredAsDerivedClass extends Promise { | |
resolve; | |
reject; | |
static get [Symbol.species]() { | |
return Promise; | |
} | |
constructor() { | |
let resolve, reject; | |
super((s, f) => { resolve = s; reject = f; }); | |
this.resolve = resolve; this.reject = reject; | |
} | |
} | |
// DeferredAsFunc | |
function DeferredAsFunc() { | |
this.promise = new Promise((s, f) => { this.resolve = s; this.reject = f; }); | |
} | |
// createDeferredAsObject | |
function createDeferredAsObject() { | |
const d = {} | |
d.promise = new Promise((s, f) => { d.resolve = s; d.reject = f; }); | |
return d; | |
} | |
// make sure each deferred works as expected | |
async function testDeferred(tag, creator, ms) { | |
const start = Date.now(); | |
console.time(tag); | |
const d = creator(); | |
setTimeout(() => d.resolve(), ms); | |
await (d.then ? d: d.promise); | |
console.timeEnd(tag); | |
console.assert(Date.now() - start >= ms); | |
} | |
const delayMs = 500; | |
await testDeferred("DeferredAsClass", () => new DeferredAsClass(), delayMs) | |
await testDeferred("DeferredAsClassWithConstructor", () => new DeferredAsClassWithConstructor(), delayMs) | |
await testDeferred("DeferredAsDerivedClass", () => new DeferredAsDerivedClass(), delayMs) | |
await testDeferred("DeferredAsFunc", () => new DeferredAsFunc(), delayMs) | |
await testDeferred("createDeferredAsObject", createDeferredAsObject, delayMs) | |
// timing | |
console.log("*** timing ***") | |
// this test can be slow in Firefox | |
const iterations = /firefox/i.test(globalThis.navigator?.userAgent) ? | |
100_000: ((globalThis.Deno || globalThis.process) ? 3_000_000: 1_000_000); | |
const cached = Promise.resolve(); | |
async function timeMany(tag, creator) { | |
console.time(tag); | |
for (let n = 0; n < iterations; n++) { | |
await creator(s => queueMicrotask(s)); | |
} | |
console.timeEnd(tag); | |
} | |
// timing new Promise directly | |
await timeMany("Promise", executor => new Promise(executor)); | |
// timing new DeferredAsClass() | |
await timeMany("DeferredAsClass", executor => { | |
const d = new DeferredAsClass(); | |
executor(d.resolve, d.reject); | |
return d.promise; | |
}); | |
// timing new DeferredAsClassWithConstructor() | |
await timeMany("DeferredAsClassWithConstructor", executor => { | |
const d = new DeferredAsClassWithConstructor(); | |
executor(d.resolve, d.reject); | |
return d.promise; | |
}); | |
// timing new DeferredAsDerivedClass() | |
await timeMany("DeferredAsDerivedClass", executor => { | |
const d = new DeferredAsDerivedClass(); | |
executor(d.resolve, d.reject); | |
return d; | |
}); | |
// timing new DeferredAsFunc() | |
await timeMany("DeferredAsFunc", executor => { | |
const d = new DeferredAsFunc(); | |
executor(d.resolve, d.reject); | |
return d.promise; | |
}); | |
// timing createDeferredAsObject | |
await timeMany("createDeferredAsObject", executor => { | |
const d = createDeferredAsObject(); | |
executor(d.resolve, d.reject); | |
return d.promise; | |
}); | |
}().catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment