-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
util: use faster -0 check #15726
util: use faster -0 check #15726
Conversation
lib/util.js
Outdated
// Format -0 as '-0'. Strict equality won't distinguish 0 from -0. | ||
if (Object.is(value, -0)) | ||
// Format -0 as '-0'. A `value === -0` check won't distinguish 0 from -0. | ||
if (1 / value === -Infinity) |
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.
Might be worth benchmarking 1 / value < 0
also.
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.
@ljharb doesn't that have a different meaning? That condition is true if value
is -Infinity
but we want to know if value
is -0
.
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.
Actually 1 / -Infinity
is -0
, so a < 0
check would evaluate to false
for value = -Infinity
. I think having the stricter check is better.
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.
Ah yes, good call. Don't mind me :-)
@bmeurer is |
|
I have a proof-of-concept for Object.is(o, -0) case by like 11x on a micro-benchmark. I guess this PR still makes sense independent of the V8 fix, since that will only land in Node 9. But maybe you wanna leave a comment that this can be changed back to |
0f6cf3a
to
4540b21
Compare
Code comment added. |
4540b21
to
8e1d76d
Compare
@mscdex Thanks! |
FYI: |
The Object.is builtin provides an entry point to the abstract operation SameValue, which properly distinguishes -0 and 0, and also identifies NaNs. Most of the time you don't need these, but rather just regular strict equality, but when you do, Object.is(o, -0) is the most readable way to check for minus zero. This is for example used in Node.js by formatNumber to properly print -0 for negative zero. However since the builtin thus far implemented as C++ builtin and TurboFan didn't know anything about it, Node.js considering to go with a more performant, less readable version (which also makes assumptions about the input value) in nodejs/node#15726 until the performance of Object.is will be on par (so hopefully we can go back to Object.is in Node 9). This CL ports the baseline implementation of Object.is to CSA, which is pretty straight-forward since SameValue is already available in CodeStubAssembler, and inlines a few interesting cases into TurboFan, i.e. comparing same SSA node, and checking for -0 and NaN explicitly. On the micro-benchmarks we go from testNumberIsMinusZero: 1000 ms. testObjectIsMinusZero: 929 ms. testObjectIsNaN: 954 ms. testObjectIsSame: 793 ms. testStrictEqualSame: 104 ms. to testNumberIsMinusZero: 89 ms. testObjectIsMinusZero: 88 ms. testObjectIsNaN: 88 ms. testObjectIsSame: 86 ms. testStrictEqualSame: 105 ms. which is a nice 10x to 11x improvement and brings Object.is on par with strict equality for most cases. Drive-by-fix: Also refactor and optimize the SameValue check in the CodeStubAssembler to avoid code bloat (by not inlining StrictEqual into every user of SameValue, and also avoiding useless checks). Bug: v8:6882 Change-Id: Ibffd8c36511f219fcce0d89ed4e1073f5d6c6344 Reviewed-on: https://chromium-review.googlesource.com/700254 Reviewed-by: Jaroslav Sevcik <[email protected]> Commit-Queue: Benedikt Meurer <[email protected]> Cr-Commit-Position: refs/heads/master@{#48275}
PR-URL: nodejs#15726 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: Yuta Hiroto <[email protected]>
8e1d76d
to
d545c94
Compare
PR-URL: nodejs/node#15726 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: Yuta Hiroto <[email protected]>
PR-URL: #15726 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: Yuta Hiroto <[email protected]>
PR-URL: #15726 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Benedikt Meurer <[email protected]> Reviewed-By: Yuta Hiroto <[email protected]>
should this land in LTS? If so it will need to bake a bit longer. Please change labels as appropriate |
Benchmark results:
CI: https://ci.nodejs.org/job/node-test-pull-request/10378/
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)