-
Notifications
You must be signed in to change notification settings - Fork 18
Iteration perf improvements #25
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
Conversation
I have checked in a new benchmark script at https://github.com/lemire/TypedFastBitSet.js/blob/master/benchmark/issue25.js Could you run it? I am getting that the for-of construction, with your PR, is still 2x slower than forEach.
I think we will merge your PR, but if your expectation is that you have bridged the performance gap... I am not sure that's the case. You should still use forEach if you care about performance, it seems. Or do I misunderstand? |
1 similar comment
I have checked in a new benchmark script at https://github.com/lemire/TypedFastBitSet.js/blob/master/benchmark/issue25.js Could you run it? I am getting that the for-of construction, with your PR, is still 2x slower than forEach.
I think we will merge your PR, but if your expectation is that you have bridged the performance gap... I am not sure that's the case. You should still use forEach if you care about performance, it seems. Or do I misunderstand? |
:) Okay, so this explanation will get weird, so I'm including an update to your benchmark. The implementation of While the iterator might still be 2x slower than And, when the only "fast" tool provided is I've included benchmark examples showing a nesting of .add("TypedFastBitSet-nested-forof", function () {
let card = 0;
for (const x of tb_small) {
for (const y of tb_small) {
for (const z of tb_small) {
card += x + y + z;
}
}
}
return card;
})
.add("TypedFastBitSet-nested-forEach", function () {
let card = 0;
tb_small.forEach(function (x) {
tb_small.forEach(function (y) {
tb_small.forEach(function (z) {
card += x + y + z;
});
});
});
return card;
}) Results:
:) I hope this helps explain the intent behind the requested change |
Interestingly, the benchmarks you have don't show a huge difference between the naive cases from master:
this PR:
Anecdotally, while testing the implementation in arbitrary Stackblitz experiments, I was seeing a 4x-5x improvement even in the naive case. 🤷♂️ |
Merging. |
Thank you very much, @lemire! LMK when you have time to publish. ❤️ |
It should have been published by now. |
Here are two commits that drastically improve the performance of using
TypedFastBitSet
andSparseTypedFastBitSet
infor..of
loops.Just to explain:
*[Symbol.iterator]()
implementations, while terse, leverage JavaScript generators which are notably slower than just returning a plain iterator object. This is because generators also support coroutines, which aren't being leveraged at all here.I'm making this PR because our team is favoring
forEach
overfor..of
for performance reasons, and if the point of this type is to make things fast, I think it should be fast in all cases.forEach(fn)
, in particular when used in a nested fashion, don't perform as well as in-lined for loops. :)Thank you for this library BTW!