由于异步生成器中的 promise 的非并行等待而导致减速 [英] Slowdown due to non-parallel awaiting of promises in async generators
问题描述
我正在使用生成器和 Bluebird 编写代码,我有以下内容:
I'm writing code using generators and Bluebird and I have the following:
var async = Promise.coroutine;
function Client(request){
this.request = request;
}
Client.prototype.fetchCommentData = async(function* (user){
var country = yield countryService.countryFor(user.ip);
var data = yield api.getCommentDataFor(user.id);
var notBanned = yield authServer.authenticate(user.id);
if (!notBanned) throw new AuthenticationError(user.id);
return {
country: country,
comments: data,
notBanned: true
};
});
但是,这有点慢,我觉得我的应用程序等待 I/O 的时间太多,而且不是并行的.如何提高应用程序的性能?
However, this is kind of slow, I feel like my application is waiting too much for I/O and it's not in parallel. How can I improve the performance of my application?
countryFor
的总响应时间为 800 + getCommentDataFor
的 400 + authenticate
的 600,所以总共 1800 毫秒,这是很多.
The total response time is 800 for countryFor
+ 400 for getCommentDataFor
+ 600 for authenticate
so in total 1800ms which is a lot.
推荐答案
您花费了太多时间等待来自不同来源的 I/O.
You are spending too much time waiting for I/O from different sources.
在普通的 Promise 代码中,您会为此使用 Promise.all
,但是 - 人们倾向于编写代码来等待带有生成器的请求.您的代码执行以下操作:
In normal promise code, you'd use Promise.all
for this, however - people have a tendency to write code that waits for requests with generators. Your code does the following:
<-client service->
countryFor..
''--..
''--..
''--.. country server sends response
..--''
..--''
..--''
getCommentDataFor
''--..
''--..
''--..
''--.. comment service returns response
..--''
..--''
..--''
authenticate
''--..
''--..
''--.. authentication service returns
..--''
..--''
..--''
Generator done.
相反,它应该这样做:
<-client service->
countryFor..
commentsFor..''--..
authenticate..''--..''--..
''--..''--..''--.. country server sends response
''--..--''.. comment service returns response
..--''..--''.. authentication service returns response
..--''..--''..
..--''..--''..--''
..--''..--''
..--''
Generator done
简单地说,您的所有 I/O 都应该在这里并行完成.
Simply put, all your I/O should be done in parallel here.
为了解决这个问题,我会使用 Promise.props
.Promise.props
接受一个对象并等待其所有属性解析(如果它们是 Promise).
To fix this, I'd use Promise.props
. Promise.props
takes an objects and waits for all its properties to resolve (if they are promises).
记住 - 生成器和承诺混合和匹配真的,你只需产生承诺:
Remember - generators and promises mix and match really well, you simply yield promises:
Client.prototype.fetchCommentData = async(function* (user){
var country = countryService.countryFor(user.ip);
var data = api.getCommentDataFor(user.id);
var notBanned = authServer.authenticate(user.id).then(function(val){
if(!val) throw new AuthenticationError(user.id);
});
return Promise.props({ // wait for all promises to resolve
country : country,
comments : data,
notBanned: notBanned
});
});
这是人们第一次使用生成器时常犯的错误.
This is a very common mistake people make when using generators for the first time.
Kris Kowal 无耻地从 Q-Connection 中截取的 ascii 艺术
这篇关于由于异步生成器中的 promise 的非并行等待而导致减速的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!