在测试await
的性能时,我发现了一个令人困惑的谜团。我在控制台中分别运行了以下每个代码段,以过滤掉吸虫,并获取相关数据的平均时间。
(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);
导致:default: 5.322021484375ms
接下来,我尝试添加制作它async
hronous
(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);
太好了! Chrome知道它的东西。非常低的开销:default: 8.712890625ms
接下来,我尝试添加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);
这导致100倍速减速:default: 724.706787109375ms
所以,必须有一些合乎逻辑的理由,对吗?我尝试先比较这些类型。
(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);
好的,所以不是这样的:default: 6.7939453125ms
那么,它必须是承诺部分:检查传递给await的项是否是一个承诺。那一定是罪魁祸首,我是对的还是我是对的?
(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);
这导致:default: 7.2041015625ms
好的,好吧,让我们给Chrome带来疑问。让我们假设一秒钟,他们编程等待远远不够完美。
(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);
但即便如此,也无法解释await
的糟糕表现:default:7.85498046875ms
好吧,老实说,我放弃了。我认为await
比现在快至少100倍。我想不出一个好理由,为什么它在完美世界中不会快100倍。但是,我们并不是生活在一个完美的世界,所以问题就在于:如何?怎么样?怎么这么慢?是否有任何希望它在未来更快(比如说,大约快100倍左右)?我正在寻找事实并对这个问题进行客观分析,这将解释我在上述性能测试中看到的令人费解的谜团。
您可以轻松地观察到await
表达与缺乏表达之间的差异。至少,您要求引擎查看微任务队列,可能还要完成因I / O完成而发生的其他工作。鉴于此,这不可能被优化为什么。
如果您真的希望将CPU旋转几毫秒,请不要写await
。
这是一个例子。它打印1 2 3
。
Promise.resolve().then(()=>console.log(2));
(async()=>{
console.log(1);
await undefined;
console.log(3);
})();
await undefined
不是一个“无所事事”的声明。这是JavaScript的合作多任务处理。