Uh oh!
There was an error while loading. Please reload this page.
buffer: add a check for byteLength in readIntBE() and readIntLE() - #11146
buffer: add a check for byteLength in readIntBE() and readIntLE()#11146seppevs wants to merge 3 commits into
Conversation
jasnell
commented
Feb 3, 2017
Added semver-major due to the addition of the new throw conditions. |
There was a problem hiding this comment.
Perhaps these can just be condensed into a single check
if(typeofbyteLength!=='number'||byteLength<=0)thrownewTypeError('"byteLength" must be a positive number greater than zero');There was a problem hiding this comment.
Thank you for your suggestion. I made the changes and amended them to the previous commit.
ca0c9be to
a8d1fa8CompareThere was a problem hiding this comment.
byteLength <= 0 should be a RangeError I think.
There was a problem hiding this comment.
So should we throw 2 separate errors (TypeError when it's not a Number and RangeError when byteLength is <= 0) or just one RangeError?
There was a problem hiding this comment.
I think separate errors would be better, because a TypeError for byteLength <= 0 doesn't look right IMO.
According to the docs:
byteLength{Integer} How many bytes to read. Must satisfy:0 < byteLength <= 6
and
Supports up to 48 bits of accuracy.
So probably check byteLength > 6 too?
Also a doc update would be great :D
There was a problem hiding this comment.
good point about the RangeError. Yes, in that case keeping them separate is best.
There was a problem hiding this comment.
Thanks again for the feedback. I amended the proposed changes to the previous commit. I also updated the docs.
f3644da to
ed56860CompareTrott
commented
Feb 3, 2017
Should a benchmark be run to ascertain the performance impact of this change? |
There was a problem hiding this comment.
Might as well adding TypeError: and RangeError: as the previous example, just to be a little bit more consistent.
joyeecheung
commented
Feb 3, 2017
@Trott +1 on running a benchmark. FYI: how to compare different implementations using the benchmark suite. The whole buffer benchmarks can take a long time IIRC, so probably running the benchmarks for these specific functions only (using |
ed56860 to
46ac4adCompareseppevs
commented
Feb 3, 2017
@joyeecheung Thanks for advice on running the benchmark suite. I will look into it. |
I think the actual byte length range checking should go inside the
|
seppevs
commented
Feb 3, 2017
@mscdex so should both the RangeError and TypeError checks be moved inside the |
joyeecheung
commented
Feb 3, 2017
+1 on putting it in |
mscdex
commented
Feb 4, 2017
@seppevs I think putting both in there would be alright, plus it would allow us to avoid any potential performance regressions. |
46ac4ad to
25668efCompareCode is updated. The checks are now inside an I also added a benchmark for the |
There was a problem hiding this comment.
The if branch should be moved outside new Function to avoid the runtime cost. Also would be easier to read if we use template literals here, something like:
varcall;if(fn==='readIntLE'||conf.type==='readIntBE'){call=`buff.${fn}(0, 1, ${noAssert})`;}else{call=`buff.${fn}(0, ${noAssert})`;}vartestFunction=newFunction('buff',` for (var i = 0; i !== ${len}; ++i) {${call}; }`);There was a problem hiding this comment.
Probably best moving checkByteLength and checkOffset in the same branch. Also not sure if the assertion should happen before or after offset and byteLength get converted into numbers, I am inclined to checking it before the conversion.
There was a problem hiding this comment.
The checkOffset uses the byteLength, and assumes it is defined and already converted to a number. The offset and byteLength are converted to numbers before the checkOffset function is invoked.
I think it's better to check the byteLength before it's converted to a number. If we do the conversion first, we can't trust the converted value in the checkByteLength function
console.log(undefined>>>0);// -> 0console.log(null>>>0);// -> 0console.log('a string'>>>0);// -> 0console.log(true>>>0);// -> 1 .... this is in the expected range and would pass the checkSo what do you suggest me to do?
There was a problem hiding this comment.
I agree that ideally we would combine the two, but there could easily be breakage if the current (prior to this PR) assertions are moved, so that would definitely be another semver-major change if we wanted to make that change at all. Thoughts @nodejs/collaborators?
There was a problem hiding this comment.
@seppevs No matter the order of the assertions, I the typechecking part of checkByteLength should be consistent with checkOffset. If checkOffset doesn't check the type, checkByteLength should not do it either. If we do want to check the type, then we need to add this to checkOffset too.
There was a problem hiding this comment.
Also if they are consistent, then they can be moved into the same branch I think? If we check the type, they can both be placed before the conversion. If we don't, they can both be placed after the conversion.
There was a problem hiding this comment.
So should I check the type, or not? Do you think the type check will affect the performance?
There was a problem hiding this comment.
@seppevs I can think of good arguments for both sides, so I think we can wait for thoughts from other collaborators.
25668ef to
d71fc82Comparejasnell
commented
Mar 22, 2017
What is the status on this one? @seppevs ... can you please rebase this? |
There was a problem hiding this comment.
You don't need the else here.
8d4fbf6 to
10c78f4Compareseppevs
commented
Mar 27, 2017
@jasnell rebase done |
jasnell
commented
Mar 27, 2017
Ping @nodejs/buffer @nodejs/ctc ... thoughts on this? |
jasnell
commented
Apr 4, 2017
ping @nodejs/ctc |
64ff873 to
43e161eCompareTrott
commented
Jan 2, 2018
@targos That would make sense. Will do... |
Trott
commented
Jan 3, 2018
Oh, yes, probably! I'm intrigued, but I am inclined to save that for a subsequent PR. This PR is 11 months old at this point. I'd rather get the functionality landed and then have the performance vs. Crankshaft-script maintenance costs debate separately. |
Trott
commented
Jan 3, 2018
Benchmark results with the additional changes: improvement confidence p.value buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntBE" buffer="fast" noAssert="false" -4.06 % *** 0.0002808920 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntBE" buffer="fast" noAssert="true" -0.87 % 0.5179050330 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntBE" buffer="slow" noAssert="false" -2.66 % 0.2197501164 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntBE" buffer="slow" noAssert="true" 0.94 % 0.3536060899 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntLE" buffer="fast" noAssert="false" -3.18 % 0.0840983107 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntLE" buffer="fast" noAssert="true" -0.39 % 0.7203410009 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntLE" buffer="slow" noAssert="false" -0.79 % 0.6929134114 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="IntLE" buffer="slow" noAssert="true" -1.10 % 0.4140083284 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntBE" buffer="fast" noAssert="false" -5.58 % *** 0.0009982531 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntBE" buffer="fast" noAssert="true" 2.90 % 0.1010858492 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntBE" buffer="slow" noAssert="false" -3.64 % * 0.0394332017 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntBE" buffer="slow" noAssert="true" -0.92 % 0.6825518346 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntLE" buffer="fast" noAssert="false" -2.84 % 0.0620117183 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntLE" buffer="fast" noAssert="true" -1.18 % 0.2374233691 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntLE" buffer="slow" noAssert="false" -5.59 % ** 0.0022420004 buffers/buffer-read-with-byteLength.js byteLength=1 millions=1 type="UIntLE" buffer="slow" noAssert="true" -0.38 % 0.8336763163 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntBE" buffer="fast" noAssert="false" -4.56 % *** 0.0001955189 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntBE" buffer="fast" noAssert="true" -1.70 % 0.1608865221 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntBE" buffer="slow" noAssert="false" -1.56 % 0.3447368715 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntBE" buffer="slow" noAssert="true" 0.28 % 0.8424978551 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntLE" buffer="fast" noAssert="false" -4.78 % ** 0.0025353959 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntLE" buffer="fast" noAssert="true" -3.36 % 0.1101136262 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntLE" buffer="slow" noAssert="false" 1.68 % 0.2885417168 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="IntLE" buffer="slow" noAssert="true" -0.36 % 0.8360745581 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntBE" buffer="fast" noAssert="false" -2.91 % 0.0563485510 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntBE" buffer="fast" noAssert="true" 2.73 % 0.0570619342 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntBE" buffer="slow" noAssert="false" -2.16 % 0.1467243882 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntBE" buffer="slow" noAssert="true" 1.09 % 0.5036428118 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntLE" buffer="fast" noAssert="false" -3.13 % * 0.0167492226 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntLE" buffer="fast" noAssert="true" 2.18 % 0.3465909913 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntLE" buffer="slow" noAssert="false" -3.78 % *** 0.0008500509 buffers/buffer-read-with-byteLength.js byteLength=2 millions=1 type="UIntLE" buffer="slow" noAssert="true" -1.13 % 0.5597913248 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntBE" buffer="fast" noAssert="false" 1.31 % 0.5323692216 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntBE" buffer="fast" noAssert="true" 0.36 % 0.7901715876 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntBE" buffer="slow" noAssert="false" -0.03 % 0.9858863031 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntBE" buffer="slow" noAssert="true" -1.51 % 0.4410258539 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntLE" buffer="fast" noAssert="false" -3.08 % * 0.0126980478 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntLE" buffer="fast" noAssert="true" 0.54 % 0.7528102406 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntLE" buffer="slow" noAssert="false" 1.42 % 0.4579209139 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="IntLE" buffer="slow" noAssert="true" -4.31 % * 0.0289903090 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntBE" buffer="fast" noAssert="false" -0.22 % 0.8495333840 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntBE" buffer="fast" noAssert="true" 2.97 % 0.0837406345 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntBE" buffer="slow" noAssert="false" -1.74 % 0.2207386083 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntBE" buffer="slow" noAssert="true" 0.78 % 0.7013668938 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntLE" buffer="fast" noAssert="false" -0.83 % 0.5471758131 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntLE" buffer="fast" noAssert="true" 0.57 % 0.7022090281 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntLE" buffer="slow" noAssert="false" -2.32 % 0.0827266784 buffers/buffer-read-with-byteLength.js byteLength=4 millions=1 type="UIntLE" buffer="slow" noAssert="true" 2.56 % 0.0564231616 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntBE" buffer="fast" noAssert="false" 1.54 % 0.3133448827 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntBE" buffer="fast" noAssert="true" 1.99 % 0.2231816540 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntBE" buffer="slow" noAssert="false" -1.60 % 0.3031854740 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntBE" buffer="slow" noAssert="true" -1.76 % 0.2391806630 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntLE" buffer="fast" noAssert="false" 1.23 % 0.4651066104 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntLE" buffer="fast" noAssert="true" 2.49 % 0.3296908645 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntLE" buffer="slow" noAssert="false" 3.36 % 0.1483373386 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="IntLE" buffer="slow" noAssert="true" 0.09 % 0.9615904952 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntBE" buffer="fast" noAssert="false" -1.27 % 0.4341473943 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntBE" buffer="fast" noAssert="true" 2.97 % 0.0836560690 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntBE" buffer="slow" noAssert="false" -1.14 % 0.5116753365 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntBE" buffer="slow" noAssert="true" 2.78 % 0.0815530806 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntLE" buffer="fast" noAssert="false" -2.89 % 0.2026249081 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntLE" buffer="fast" noAssert="true" -0.88 % 0.4983282113 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntLE" buffer="slow" noAssert="false" -0.26 % 0.8405160659 buffers/buffer-read-with-byteLength.js byteLength=6 millions=1 type="UIntLE" buffer="slow" noAssert="true" -0.34 % 0.7890584482 |
Trott
commented
Jan 3, 2018
New benchmark results show an even smaller perf hit than before. 🎉 |
Trott
commented
Jan 3, 2018
I imagine the |
Trott
commented
Jan 3, 2018
Trott
commented
Jan 4, 2018
Lone CI failure is a known flaky for which there is a fix pending (#17958). CI is good. |
Trott
commented
Jan 4, 2018
Previous reviewers, a re-review is probably in order. Sorry about that. On the upside, I think this is probably good to go at this point. PTAL |
The 'byteLength' argument should be required and of type 'number'. It should have a value between 1 and 6. This is a fix for issue: nodejs#10515
Split them into their own benhmark file and use different byteLength values.
4a5d043 to
710d1dcCompareThe 'byteLength' argument should be required and of type 'number'. It should have a value between 1 and 6. PR-URL: nodejs#11146Fixes: nodejs#10515 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Split them into their own benhmark file and use different byteLength values. PR-URL: nodejs#11146 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs#11146 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
The 'byteLength' argument should be required and of type 'number'. It should have a value between 1 and 6.
This is a fix for issue: #10515
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passesAffected core subsystem(s)
buffer