-
Notifications
You must be signed in to change notification settings - Fork 21
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
feat: add bufferlike variants #50
Conversation
Everything in this library needs to be compatible with browsers, so any Node specific API can unfortunately not be used. Besides that, any additional API (adding two methods here) needs to be documented, tested and showing benchmarks to support the claim of being faster. I haven't benchmarked it, but it would surprise me a fair bit that the overall effect is anything but marginal, as the copy happens once and isn't in the performance critical part (may have a noticeable effect on very large inputs). I'd welcome any performance improvement, however small, as long as they are compatible with all targeted engines. |
The difference is somewhat significant for small strings (e.g. hashing names):
https://gist.github.com/ronag/370da9efaf00358805ee6aa020671e3c |
That is quite surprising, to decouple the copy from the hashing itself, I ran a bench with just the copy. async function runBench() {
const buf = new Uint8Array(1e8);
for (let i = 1; i <= 1e8; i *= 10) {
const suite = new Benchmark.Suite(`${i} bytes`, handlers);
const input = Buffer.from(randomString(i));
suite
.add("Buffer.copy()", () => {
input.copy(buf);
})
.add("Array.set()", () => {
buf.set(input);
})
.run();
}
} The small inputs are definitely much faster, about 10%, but that is pretty much gone after 1000 bytes.
But as you mentioned, that was on Node 22.7. For comparison, Node 20.17 is much slower with
As already mentioned, it is not compatible with browsers, furthermore it gets even more confusing when you'd need to consider different versions of Node. |
Do we know what the specific node version that introduced the improvement happens to be? |
Node 22.7. |
This is what we are actually doing. We are not passing https://gist.github.com/ronag/4f40ab7c3b18cb9a5320e47e67a42dd4 Then the difference is even more significant:
|
@ronag seeing that you contributed the performance improvements of I'm just wondering because having an overload of |
The biggest problem with the browser API is that it's super slow to create sub arrays. Which was the original problem which that PR was trying to resolve. The fact that it was also faster with non-partial copies was an unexpected benefit. i.e. this Is not possible to optimize and is super slow: dst.set(src.subarray(start, end)) Hence this is much faster: src.copy(dst, 0, start, end) |
Looks like V8 does a lot of more check related to whether or not the buffer is attached and shared array backings store which node buffers don't support. https://github.com/v8/v8/blob/main/src/builtins/typed-array-set.tq |
Okay interesting. I figured it was V8 but I thought Node had some bridge between them. Anyway, if V8 could have these improvements, everyone would win, but I suspect they have some extra checks for the validity of the memory or something. The Lines 69 to 99 in 1288bfe
So there would be some potential there for a Node specific version, but since it's literally all that happens on the JS side, that would essentially mean a completely different module for Node vs. Browser. Since I'm not planning to actively develop this further, and having different modules seems like a nightmare in general, any changes should remain engine agnostic. |
Sure no problem. We have our own fork for our needs. Just thought we'd try to contribute back. |
Thanks and I also appreciate the insights into the Node specific parts. |
Buffer.copy
is faster thanUint8Array.set
in Node 22.7+