How much is the performance overhead for awaiting an already fulfilled Promise?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
While doing code reviews, I've recently come across such kind of code blocks:
const promises = ;
const data = ;
for (let piece of pieces) {
for (let chunk of piece) {
promises.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data = await Promise.all(promises);
}
Here pieces
is an array of arrays. Note that due to certain constraints we cannot await
all Promises at once, hence this sort of chunking.
In my feedback, I write that this appears to be an anti-pattern as we are also awaiting Promises which were resolved in the previous iterations and the following is the proper way of handling such scenarios:
const data = ;
for (let piece of pieces) {
const promises = ;
for (let chunk of piece) {
promies.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data.push(... await Promise.all(promises));
}
At the end, data
will be the same in both cases.
I understand how data
is being populated in both cases. I would like to know how much is the performance overhead of awaiting an already fulfilled promise (which is happening in the first code block) and is it significant?
javascript node.js asynchronous promise async-await
|
show 8 more comments
While doing code reviews, I've recently come across such kind of code blocks:
const promises = ;
const data = ;
for (let piece of pieces) {
for (let chunk of piece) {
promises.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data = await Promise.all(promises);
}
Here pieces
is an array of arrays. Note that due to certain constraints we cannot await
all Promises at once, hence this sort of chunking.
In my feedback, I write that this appears to be an anti-pattern as we are also awaiting Promises which were resolved in the previous iterations and the following is the proper way of handling such scenarios:
const data = ;
for (let piece of pieces) {
const promises = ;
for (let chunk of piece) {
promies.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data.push(... await Promise.all(promises));
}
At the end, data
will be the same in both cases.
I understand how data
is being populated in both cases. I would like to know how much is the performance overhead of awaiting an already fulfilled promise (which is happening in the first code block) and is it significant?
javascript node.js asynchronous promise async-await
1
the two code blocks are not identical at all ... the first one will end up with less data than the second in data
– Jaromanda X
Nov 24 '18 at 6:52
The intent here is pretty unclear. Certainly if this is about gathering todata
then both listings are likely not that ideal. To clarify comments I've seen here so far example 1 is "re-assigning" thedata
and 2. Is "attempting" to accumulate. Unfortunately it's all a bit "meta" to really understand context here. And without context, any answer really lacks any meaning. Best if the comments cool down and allow the OP to clarify.
– Neil Lunn
Nov 24 '18 at 6:55
if you take 2nd variant andawait data
outside the loops it would be fastest option
– skyboyer
Nov 24 '18 at 6:57
1
Sorry @sbmthakur I was distracted by the last part of the code and missed the nesting difference.
– Mark Meyer
Nov 24 '18 at 7:01
1
@CertainPerformance no, they are still Promises.
– skyboyer
Nov 24 '18 at 7:04
|
show 8 more comments
While doing code reviews, I've recently come across such kind of code blocks:
const promises = ;
const data = ;
for (let piece of pieces) {
for (let chunk of piece) {
promises.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data = await Promise.all(promises);
}
Here pieces
is an array of arrays. Note that due to certain constraints we cannot await
all Promises at once, hence this sort of chunking.
In my feedback, I write that this appears to be an anti-pattern as we are also awaiting Promises which were resolved in the previous iterations and the following is the proper way of handling such scenarios:
const data = ;
for (let piece of pieces) {
const promises = ;
for (let chunk of piece) {
promies.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data.push(... await Promise.all(promises));
}
At the end, data
will be the same in both cases.
I understand how data
is being populated in both cases. I would like to know how much is the performance overhead of awaiting an already fulfilled promise (which is happening in the first code block) and is it significant?
javascript node.js asynchronous promise async-await
While doing code reviews, I've recently come across such kind of code blocks:
const promises = ;
const data = ;
for (let piece of pieces) {
for (let chunk of piece) {
promises.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data = await Promise.all(promises);
}
Here pieces
is an array of arrays. Note that due to certain constraints we cannot await
all Promises at once, hence this sort of chunking.
In my feedback, I write that this appears to be an anti-pattern as we are also awaiting Promises which were resolved in the previous iterations and the following is the proper way of handling such scenarios:
const data = ;
for (let piece of pieces) {
const promises = ;
for (let chunk of piece) {
promies.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
}
data.push(... await Promise.all(promises));
}
At the end, data
will be the same in both cases.
I understand how data
is being populated in both cases. I would like to know how much is the performance overhead of awaiting an already fulfilled promise (which is happening in the first code block) and is it significant?
javascript node.js asynchronous promise async-await
javascript node.js asynchronous promise async-await
edited Nov 24 '18 at 12:39
Bergi
382k64587920
382k64587920
asked Nov 24 '18 at 6:43
sbmthakursbmthakur
456
456
1
the two code blocks are not identical at all ... the first one will end up with less data than the second in data
– Jaromanda X
Nov 24 '18 at 6:52
The intent here is pretty unclear. Certainly if this is about gathering todata
then both listings are likely not that ideal. To clarify comments I've seen here so far example 1 is "re-assigning" thedata
and 2. Is "attempting" to accumulate. Unfortunately it's all a bit "meta" to really understand context here. And without context, any answer really lacks any meaning. Best if the comments cool down and allow the OP to clarify.
– Neil Lunn
Nov 24 '18 at 6:55
if you take 2nd variant andawait data
outside the loops it would be fastest option
– skyboyer
Nov 24 '18 at 6:57
1
Sorry @sbmthakur I was distracted by the last part of the code and missed the nesting difference.
– Mark Meyer
Nov 24 '18 at 7:01
1
@CertainPerformance no, they are still Promises.
– skyboyer
Nov 24 '18 at 7:04
|
show 8 more comments
1
the two code blocks are not identical at all ... the first one will end up with less data than the second in data
– Jaromanda X
Nov 24 '18 at 6:52
The intent here is pretty unclear. Certainly if this is about gathering todata
then both listings are likely not that ideal. To clarify comments I've seen here so far example 1 is "re-assigning" thedata
and 2. Is "attempting" to accumulate. Unfortunately it's all a bit "meta" to really understand context here. And without context, any answer really lacks any meaning. Best if the comments cool down and allow the OP to clarify.
– Neil Lunn
Nov 24 '18 at 6:55
if you take 2nd variant andawait data
outside the loops it would be fastest option
– skyboyer
Nov 24 '18 at 6:57
1
Sorry @sbmthakur I was distracted by the last part of the code and missed the nesting difference.
– Mark Meyer
Nov 24 '18 at 7:01
1
@CertainPerformance no, they are still Promises.
– skyboyer
Nov 24 '18 at 7:04
1
1
the two code blocks are not identical at all ... the first one will end up with less data than the second in data
– Jaromanda X
Nov 24 '18 at 6:52
the two code blocks are not identical at all ... the first one will end up with less data than the second in data
– Jaromanda X
Nov 24 '18 at 6:52
The intent here is pretty unclear. Certainly if this is about gathering to
data
then both listings are likely not that ideal. To clarify comments I've seen here so far example 1 is "re-assigning" the data
and 2. Is "attempting" to accumulate. Unfortunately it's all a bit "meta" to really understand context here. And without context, any answer really lacks any meaning. Best if the comments cool down and allow the OP to clarify.– Neil Lunn
Nov 24 '18 at 6:55
The intent here is pretty unclear. Certainly if this is about gathering to
data
then both listings are likely not that ideal. To clarify comments I've seen here so far example 1 is "re-assigning" the data
and 2. Is "attempting" to accumulate. Unfortunately it's all a bit "meta" to really understand context here. And without context, any answer really lacks any meaning. Best if the comments cool down and allow the OP to clarify.– Neil Lunn
Nov 24 '18 at 6:55
if you take 2nd variant and
await data
outside the loops it would be fastest option– skyboyer
Nov 24 '18 at 6:57
if you take 2nd variant and
await data
outside the loops it would be fastest option– skyboyer
Nov 24 '18 at 6:57
1
1
Sorry @sbmthakur I was distracted by the last part of the code and missed the nesting difference.
– Mark Meyer
Nov 24 '18 at 7:01
Sorry @sbmthakur I was distracted by the last part of the code and missed the nesting difference.
– Mark Meyer
Nov 24 '18 at 7:01
1
1
@CertainPerformance no, they are still Promises.
– skyboyer
Nov 24 '18 at 7:04
@CertainPerformance no, they are still Promises.
– skyboyer
Nov 24 '18 at 7:04
|
show 8 more comments
1 Answer
1
active
oldest
votes
The overhead is minuscule - it needs to iterate the already fulfilled promise, inspect it, take out the data and put it inside the result array. Assuming native promises, I expect this to be optimised and not need a roundtrip to the event loop, if you had thenables in the array then all of them would need to get resolved to a promise and that promise would need to be awaited asynchronously, taking a toll on the promise job queue.
The overhead in processing time will not be significant compared to the actual asynchronous work done in your execute
function.
However, no matter how small the overhead is, the issue with the first version of your code is that its runtime complexity is quadratic: Promise.all
needs to iterate the whole promises
array every time. The more chunks * pieces you have, the more pronounced the effect will be. I agree with your review feedback and would recommend the second version of the code.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53455835%2fhow-much-is-the-performance-overhead-for-awaiting-an-already-fulfilled-promise%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The overhead is minuscule - it needs to iterate the already fulfilled promise, inspect it, take out the data and put it inside the result array. Assuming native promises, I expect this to be optimised and not need a roundtrip to the event loop, if you had thenables in the array then all of them would need to get resolved to a promise and that promise would need to be awaited asynchronously, taking a toll on the promise job queue.
The overhead in processing time will not be significant compared to the actual asynchronous work done in your execute
function.
However, no matter how small the overhead is, the issue with the first version of your code is that its runtime complexity is quadratic: Promise.all
needs to iterate the whole promises
array every time. The more chunks * pieces you have, the more pronounced the effect will be. I agree with your review feedback and would recommend the second version of the code.
add a comment |
The overhead is minuscule - it needs to iterate the already fulfilled promise, inspect it, take out the data and put it inside the result array. Assuming native promises, I expect this to be optimised and not need a roundtrip to the event loop, if you had thenables in the array then all of them would need to get resolved to a promise and that promise would need to be awaited asynchronously, taking a toll on the promise job queue.
The overhead in processing time will not be significant compared to the actual asynchronous work done in your execute
function.
However, no matter how small the overhead is, the issue with the first version of your code is that its runtime complexity is quadratic: Promise.all
needs to iterate the whole promises
array every time. The more chunks * pieces you have, the more pronounced the effect will be. I agree with your review feedback and would recommend the second version of the code.
add a comment |
The overhead is minuscule - it needs to iterate the already fulfilled promise, inspect it, take out the data and put it inside the result array. Assuming native promises, I expect this to be optimised and not need a roundtrip to the event loop, if you had thenables in the array then all of them would need to get resolved to a promise and that promise would need to be awaited asynchronously, taking a toll on the promise job queue.
The overhead in processing time will not be significant compared to the actual asynchronous work done in your execute
function.
However, no matter how small the overhead is, the issue with the first version of your code is that its runtime complexity is quadratic: Promise.all
needs to iterate the whole promises
array every time. The more chunks * pieces you have, the more pronounced the effect will be. I agree with your review feedback and would recommend the second version of the code.
The overhead is minuscule - it needs to iterate the already fulfilled promise, inspect it, take out the data and put it inside the result array. Assuming native promises, I expect this to be optimised and not need a roundtrip to the event loop, if you had thenables in the array then all of them would need to get resolved to a promise and that promise would need to be awaited asynchronously, taking a toll on the promise job queue.
The overhead in processing time will not be significant compared to the actual asynchronous work done in your execute
function.
However, no matter how small the overhead is, the issue with the first version of your code is that its runtime complexity is quadratic: Promise.all
needs to iterate the whole promises
array every time. The more chunks * pieces you have, the more pronounced the effect will be. I agree with your review feedback and would recommend the second version of the code.
answered Nov 24 '18 at 12:37
BergiBergi
382k64587920
382k64587920
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53455835%2fhow-much-is-the-performance-overhead-for-awaiting-an-already-fulfilled-promise%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
the two code blocks are not identical at all ... the first one will end up with less data than the second in data
– Jaromanda X
Nov 24 '18 at 6:52
The intent here is pretty unclear. Certainly if this is about gathering to
data
then both listings are likely not that ideal. To clarify comments I've seen here so far example 1 is "re-assigning" thedata
and 2. Is "attempting" to accumulate. Unfortunately it's all a bit "meta" to really understand context here. And without context, any answer really lacks any meaning. Best if the comments cool down and allow the OP to clarify.– Neil Lunn
Nov 24 '18 at 6:55
if you take 2nd variant and
await data
outside the loops it would be fastest option– skyboyer
Nov 24 '18 at 6:57
1
Sorry @sbmthakur I was distracted by the last part of the code and missed the nesting difference.
– Mark Meyer
Nov 24 '18 at 7:01
1
@CertainPerformance no, they are still Promises.
– skyboyer
Nov 24 '18 at 7:04