`await` Slower Than It Should Be In Chrome

  • A+
Category:Languages

While testing the performance of await, I uncovered a confounding mystery. I ran each of the following code snippets several times each in the console to filter out flukes, and took the average times of the relevant data.

(function(console){     "use strict";     console.time();     var O = [1];     for (var i=0; i !== 107000; ++i) {         const O_0 = O[0];         O[0] = O_0;     }     console.timeEnd(); })(console); 

Resulting in: default: 5.322021484375ms

Next, I tried adding making it asynchronous

(async function(console){     "use strict";     console.time();     var O = [1];     for (var i=0; i !== 107000; ++i) {         const O_0 = O[0];         O[0] = O_0;     }     console.timeEnd(); })(console); 

Nice! Chrome knows its stuff. Very low overhead: default: 8.712890625ms

Next, I tried adding await.

(async function(console){     "use strict";     console.time();     var O = [1];     for (var i=0; i !== 107000; ++i) {         const O_0 = O[0];         O[0] = await O_0;     }     console.timeEnd(); })(console); 

This results in 100x speed reduction: default: 724.706787109375ms

So, there must be some logical reason, right? I tried comparing the types prior.

(async function(console){     "use strict";     console.time();     var O = [1];     for (var i=0; i !== 107000; ++i) {         const O_0 = O[0];         O[0] = typeof O_0 === "object" ? await O_0 : O_0;     }     console.timeEnd(); })(console); 

Okay, so that is not it: default: 6.7939453125ms

So then, it must be the promise-part: checking to see if the item passed to await is a promise. That must be the culprit, am I right or am I right?

(async function(console, Promise){     "use strict";     const isPromise = Promise.prototype.isPrototypeOf.bind(Promise);     console.time();     var O = [1];     for (var i=0; i !== 107000; ++i) {         const O_0 = O[0];         O[0] = isPromise(O_0) ? await O_0 : O_0;     }     console.timeEnd(); })(console, Promise); 

This results in: default: 7.2041015625ms

Okay, okay, let us give Chrome the benefit of the doubt. Let us assume, for a second, that they programmed await far less than perfectly.

(async function(console, Promise){     "use strict";     const isPromise = Promise.prototype.isPrototypeOf.bind(Promise.prototype);     console.time();     var O = [1];     for (var i=0; i !== 107000; ++i) {         const O_0 = O[0];       const isAnObject = typeof O_0 === "object" ? true : false;       const isPromise = isPromise(O_0);         O[0] = isAnObject && isPromise ? await O_0 : O_0;   }     console.timeEnd(); })(console, Promise); 

But even this fails to explain the poor performance of await: default:7.85498046875ms

Okay, honestly, I give up. I would think that await would be at least 100x faster than it is now. I cannot think of a single good reason why it would not be 100x faster in a perfect world. However, we do not live in a perfect world, so there inlies the question: how? How? How is it this slow? Is there any hope of it being any faster in the future (like maybe, say, around about 100x faster)? I am looking for facts and an objective analysis of this issue that would explain the puzzling mystery I am seeing in the above performance tests.

 


You can easily observe a difference between an await expression and lack thereof. At the very least, you are asking the engine to look at the microtask queue, possibly doing other work that happened as a result of I/O completing. Given that, this cannot possibly be optimized into nothing.

If you truly wish to spin the CPU for a few milliseconds, don't write await.

Here's an example. It prints 1 2 3.

Promise.resolve().then(()=>console.log(2));  (async()=>{   console.log(1);   await undefined;   console.log(3); })();

await undefined is not a "do-nothing" statement. It's JavaScript's cooperative multitasking.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: