最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - `await` Slower Than It Should Be In Chrome - Stack Overflow

programmeradmin1浏览0评论

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 paring 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 isAnObject = typeof O[0] === "object" ? true : false;
        const isThisAPromise = isPromise(O[0]);
        O[0] = isAnObject && isThisAPromise ? 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.

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 paring 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 isAnObject = typeof O[0] === "object" ? true : false;
        const isThisAPromise = isPromise(O[0]);
        O[0] = isAnObject && isThisAPromise ? 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.

Share Improve this question edited Sep 15, 2018 at 23:01 Jack G asked Sep 7, 2018 at 11:37 Jack GJack G 5,3902 gold badges46 silver badges54 bronze badges 6
  • 8 What is the puzzling mystery? Fulfilling promises takes time. The engine needs to allow other tasks to run. Without await, Chrome can concentrate on doing your task. With 107000 awaits, it's like trying to program while you have a chatty boss ing to bug you about every little thing all the damn time. – Amadan Commented Sep 7, 2018 at 11:45
  • 4 I'm not sure what is the benefit of paring promises to synchronous execution? Shouldn't you rather pare async/await with a then chain? – Bergi Commented Sep 7, 2018 at 11:49
  • 5 Notice that await does not check whether the awaited value is a promise, and continues synchronously when it is not. It always does Promise.resolve(value) and waits for that, at least one tick. You shouldn't be surprised that doing await conditionally (and in your case, never, as none of your awaited values are promises) is as fast as not doing await at all. – Bergi Commented Sep 7, 2018 at 11:52
  • 3 I mean, it might be flippant, but it's right there in the name: await. Who knew that waiting takes time. :) – Amadan Commented Sep 7, 2018 at 12:06
  • 2 @JackGiffin But there is a delay - any value is converted to a promise and then waited for, also allowing other concurrent promise chains to make progress. Just don't pass non-promise objects to await - as you demonstrated it is as fast as you expect! – Bergi Commented Sep 7, 2018 at 13:05
 |  Show 1 more ment

1 Answer 1

Reset to default 10

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 pleting. 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.

发布评论

评论列表(0)

  1. 暂无评论