Uh oh!
There was an error while loading. Please reload this page.
stream: use instanceof when checking chunk type - #19872
Conversation
Use the `instanceof` operator instead of `Stream._isUint8Array()` when checking if a chunk is a `Uint8Array` as this is faster.
lpinca
commented
Apr 7, 2018
devsnek
commented
Apr 7, 2018
i feel compelled to mention |
@devsnek |
@lpinca why not then change util.types.isUint8Array to use instanceof |
lpinca
commented
Apr 7, 2018
Yes it makes sense. |
It seems that // start: copied from /lib/internal/util/types.jsconstReflectApply=Reflect.apply;functionuncurryThis(func){return(thisArg, ...args)=>ReflectApply(func,thisArg,args);}constTypedArrayPrototype=Object.getPrototypeOf(Uint8Array.prototype);constTypedArrayProto_toStringTag=uncurryThis(Object.getOwnPropertyDescriptor(TypedArrayPrototype,Symbol.toStringTag).get);functionisUint8Array(value){returnTypedArrayProto_toStringTag(value)==='Uint8Array';}// end: copied from /lib/internal/util/types.jsleta={__proto__:Uint8Array.prototype}console.log(ainstanceofUint8Array,// trueisUint8Array(a)// false)Also see (Uint8Array might also in the same case): https://stackoverflow.com/a/22289982 |
lpinca
commented
Apr 7, 2018
@anliting good point. That's a good reason to not change |
addaleax
commented
Apr 7, 2018
This might potentially be breaking because If you are looking for a faster alternative, did you try
That defeats the purpose of having these functions – the |
lpinca
commented
Apr 8, 2018
It has the same performance of constassert=require('assert');classFoo{get[Symbol.toStringTag](){return'Uint8Array';}}constfoo=newFoo();assert(foo[Symbol.toStringTag]==='Uint8Array'); |
BridgeAR
commented
Apr 8, 2018
In general: I am a fan of having strict type checks. In this specific case, I believe it will not make a difference besides the performance gain, so I am +1.
The first check does not seem to be breaking, because it will just allow weird chunks to be accepted instead of throwing an error. The second entry seems different though and it could be counted as breaking. But why would someone want to try to pass in a manipulated chunk? It would only be bad for the user in that case, so I do not see an issue there either. |
The compatibility issue at play is that this will no longer accept Uint8Array objects from other contexts. I am not convinced this is a good idea. It’s not that this new check is “not as strict,” but rather “not as correct.” I would also be very much surprised if the result from this benchmark affects any real-world applications of Node.js. |
I will also note that V8 has been willing to do more optimizations on |
BridgeAR
commented
Apr 8, 2018
@TimothyGu thanks a lot for bringing up the context. I did not think about that anymore. |
BridgeAR
commented
Apr 8, 2018
The referenced issue is marked as fixed. So master should already reflect that performance boost with the |
Yes, it is no longer 2/3x slower but still not as fast as Also please take a look at #19559 which is the reason why I would like to make |
addaleax
commented
Apr 8, 2018
Yes, it’s a general issue with Also, by the way: We did move away from
It can be fooled, but if it is, I think we can assume that it’s intentional – and the approach does work in a multi-context way. Benchmark CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/153/ |
lpinca
commented
Apr 8, 2018
@addaleax yes my point was that we still have the context issue in other places in particular with Fooling |
addaleax
commented
Apr 8, 2018
Not really, I guess.
I don’t know, tbh. Fwiw, here’s the PR that originally moved away from |
lpinca
commented
Apr 8, 2018
I remember, |
BridgeAR
commented
Apr 8, 2018
With Turbofan |
addaleax
commented
Apr 8, 2018
@lpinca How did you benchmark this? The benchmark CI shows no significant results for streams (positive or negative), which is kind of surprising to me. |
lpinca
commented
Apr 9, 2018
@addaleax benchmark source is in PR description. You started it on master where the impact is low. |
addaleax
commented
Apr 9, 2018
@lpinca I see – I’m not sure then what to think. I would probably consider this a breaking change, but it seems like the places where we’d actually want it are v8.x and v9.x? |
lpinca
commented
Apr 9, 2018
Yes, if it can't be backported it doesn't make sense. it's a ~6% improvement on read and ~6% on write, not bad for duplex streams, multiply that for thousands of streams and the gain is not insignificant imho. There are no explicit -1 yet but it seems people are inclined toward that. If anyone makes it explicit I'll close this. |
BridgeAR
commented
Apr 12, 2018
I have no strong opinion about this and would like to defer this to @addaleax |
lpinca
commented
Apr 16, 2018
No approvals or disapprovals, this is going nowhere, closing. |
Use the
instanceofoperator instead ofStream._isUint8Array()whenchecking if a chunk is a
Uint8Arrayas this is faster.Node.js 9.11.1:
Node.js master:
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes