-
Notifications
You must be signed in to change notification settings - Fork 22.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce assertion about performance #36053
Conversation
Correct wording that implies the iterator helps are always more efficient. It is a trade off and depends on operations and the size of the array. Creating iterators and the iterator protocol has its own cost.
Do you have benchmarks? The second one goes through strictly fewer operations than the first one, so unless the array
The array method also needs to first create an iterator because the initial value is a map. |
Why do you believe it is fewer operations? Also, Array methods do not use
the iterator protocol (they predate it) which is inherently more expensive
than array iteration. Even if this particular operation is faster, as
written it implies it is faster for all operations using iterator helpers
is which is not true.
…On Wed, Sep 25, 2024, 2:24 PM Joshua Chen ***@***.***> wrote:
Do you have benchmarks? The second one goes through strictly fewer
operations than the first one, so unless the array reduce method has been
heavily optimized I don't believe it's a "may".
Creating iterators and the iterator protocol has its own cost.
The array method also needs to first create an iterator because the
initial value is a map.
—
Reply to this email directly, view it on GitHub
<#36053 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAJQGKSSW3BGKPVBUD5BISTZYMS2FAVCNFSM6AAAAABO3NU6BCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNZVGI4DSOJSGU>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Here's what I mean. You are comparing the following two: [...map.values()].reduce((a, b) => a + b);
map.values().reduce((a, b) => a + b); The first one:
The second one:
Both have to iterate through the Iterator exactly once, and both have to perform N additions, but the second version avoids the extra work of allocating an array, populating it, index-accessing it, and discarding it. |
I just ran a benchmark to try to make a point that, even for this simple reduce-only case, iterator helpers would still lose to a basic for loop, even if they beat the array methods. But I was surprised that the array methods actually soundly beat the iterator helpers and ended up neck-and-neck with the for loop. In any case, my main point was that leading off with such a trivial example is misleading because even if the case of a simple |
I don't think that's the issue. Again |
Thanks for the benchmark though, confirms our belief that new methods, no matter how seemingly efficient they are, can never beat old and manual ways of doing things. I'm okay to soften the language here since we can never be assertive about performance. |
files/en-us/web/javascript/reference/global_objects/iterator/index.md
Outdated
Show resolved
Hide resolved
Also by the way, your benchmark is way too small to be comparative. I changed the setup to: var nameToDeposit = new Map();
for (let i = 0; i < 100000; i++) {
nameToDeposit.set(i, i);
}
var sink = 0; So, array methods still beat iterator methods by a constant factor, but for loop is by far the fastest, which is very reasonable, because it avoids calling a user-provided callback (callback-based APIs are always the slowest). |
I think you misunderstand your example:
Loop incrementing is a more local operation and thus easier to optimize and this is why the first is faster. Also the first is likely more memory "efficient" in that there are fewer object allocations, while the second can minimize peek memory for larger arrays. But at the point that one is handling very large arrays, one should should not be using these methods if you care about efficiency as you would be significantly better off using a simple loop rather than these methods at all. Therefore, I would argue that you should only say that these methods are convenient and nothing about efficiency until there is some some evidence otherwise. |
Let's think about the underlying implementation. // [...map.values()]
const array = [];
for (const v of map.values()) {
array.push(v);
}
// arr.reduce((a, b) => a + b)
let acc = array[0];
const callback = (a, b) => a + b;
for (let i = 1; i < array.length; i++) {
acc = callback(acc, array[i]);
}
const iter = map.values();
let acc = iter.next().value;
for (const v of iter) {
callback(acc, v);
} The |
Ah drat you are right.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, thanks
* Update index.md Correct wording that implies the iterator helps are always more efficient. It is a trade off and depends on operations and the size of the array. Creating iterators and the iterator protocol has its own cost. * Update files/en-us/web/javascript/reference/global_objects/iterator/index.md --------- Co-authored-by: Joshua Chen <[email protected]>
Correct wording that implies the iterator helps are always more efficient. It is a trade off and depends on operations and the size of the array. Creating iterators and the iterator protocol has its own cost.
Description
Change "is" to "may be"
Motivation
Correct wording that implies the iterator helps are always more efficient. It is a trade off and depends on operations and the size of the array. Creating iterators and the iterator protocol has its own cost.