-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
buffer: stricter Buffer.isBuffer #11961
Conversation
t(null, false); | ||
t(undefined, false); | ||
t(() => {}, false); | ||
|
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.
Why the blank line here?
'use strict'; | ||
require('../common'); | ||
const assert = require('assert'); | ||
const { Buffer } = require('buffer'); |
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.
No need to require this, 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.
@cjihrig Our linter forbids using Buffer
via the global
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.
Our linter forbids using Buffer via the global
That's only in lib
. Tests like this (as well as benchmarks and tools) can use the Buffer
global and the linter won't complain.
A couple of things:
¹ edit: That’s orthogonal to this PR, I’m not fundamentally opposed to a change like this or anything |
It can be taken both ways, but I think it is a semver-patch since an object with merely
😕 That does mean that we have to walk the prototype chain instead of simply relying on the prototype being the same as
As you have remarked it's orthogonal to this change, but independent with it. |
|
Agreed! But still, sometimes bugfixes are semver-major and we have to live with that… the example from the issue is constructed enough to not worry about that, I’d say. |
We likely need to hold off on this until we decide what we're doing with Buffer in general. |
I still would like to advance this – if only the |
Ping @nodejs/buffer |
I think that the JS Buffer check is used enough that performance is a concern, and simply checking whether the argument is obviously not a Buffer is acceptable. Buffers always end up being passed to C++ anyway where they need to be checked again. Or we could go the cheap route and set something like: const is_buffer_symbol = Symbol('this is a Buffer fool!');
function Buffer() {
this[is_buffer_symbol] = true;
} Seems ridiculous, and of course the user could use While checking the performance of the call, I'd prioritize for when |
(removed my previous comment about |
@trevnorris The |
I think the idea from @trevnorris to use a Symbol is good. It should probably yield the best performance result and it is safe for inheritance. @TimothyGu would you mind rebasing and giving that a try? |
Ping @TimothyGu once more. |
Last time I checked, this PR actually increases the performance of I'll try to address the rest of the questions and get this up to date tonight. |
Make "fake" Buffer subclasses whose instances are not valid Uint8Arrays fail the test. Fixes: nodejs#11954
Unfortunately the performance of isUint8Array (or any C++ methods) on TurboFan seems to be very much subpar... I have rebased this but will temporarily put this on hold. |
88cf96b
to
ee2d44a
Compare
@TimothyGu that is not totally correct. I just benchmarked this on my own and I do not see any way to improve this a lot currently anymore. The reason is not that isUint8Array is slow but because v8 6.0 improved instanceof significantly. Comparing Node.js 8.2 to 8.3 (only three runs)
Comparing Node.js master with a symbol check
So using a symbol check can indeed improve the performance in some circumstances but it is a slowdown for the average case. As instanceof might actually get improved further by v8 in the future, I think it is safe to stick to the instanceof, especially as we now know that it got insanely fast (between 250-350 million operations per second in the benchmark. These numbers are so high that I am not even sure if the benchmark is indeed still testing what it should). I am closing this as I doubt that we can really improve any instanceof checks from now on much further. If anyone disagrees, please reopen. |
Make "fake" Buffer subclasses whose instances are not valid Uint8Arrays fail the test.
Performance-wise, there are two options for this PR: one is to simply add an
isUint8Array
check and be done with it (w/o 88cf96b). It makes non-Buffers a lot faster, but Buffers slower:Because of the decrease in performance of actual buffers, I exploited the fact that currently subclassing Buffer is not possible due to #4701, and only checked
[[Prototype]]
of the value itself (rather than going up the prototype chain asinstanceof
does). I can remove 88cf96b if it is deemed to be less future-proof but it does help out the performance a lot.Fixes: #11954
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
buffer