-
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,assert: improve comparison performance #22197
Conversation
Perhaps the V8 patch should be done in a separate PR for easier management? Additionally, the |
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.
There's a ton of stuff here:
- There's a refactoring of the buffer benchmarks
- There's a change to make comparisons.js safe to tampering of primitives
- There's a v8 patch and tests for it
- There's a complete rewrite of strictDeepEqual
I don't understand why it's all in one PR - it makes it hard to review.
In general terms I'm very +1 on the changes and it looks like good code - it's just hard to review right now.
@mscdex thanks, I forgot about that. It is now fixed. I have all the things together in one PR because they mainly rely on each other and quite a few would cause conflicts otherwise. Since you both would rather have the PR split up, I'll do that tough. |
I moved some parts and I'll wait until those land and then rebase this PR. |
dba237a
to
546275b
Compare
Here the benchmark results for strict mode: These performance improvements are on top of the ones in #22258. Benchmark
|
PTAL @nodejs/util @nodejs/testing |
@joyeecheung @addaleax [EDIT: Used |
Rerun the CI https://ci.nodejs.org/job/node-test-commit/20612/ ✔️ |
It would be great to get a review. I have a follow up optimization for util inspect that requires the same c++ function and I wait for opening the PR until this lands. |
I'm sorry, I read the code and it looks good to me but I don't understand it well enough to LGTM and would prefer it if someone who has more experience with the API review it. If you don't get a review in 48 hours ping me and I'll go through the V8 changes very carefully and review. Also, pinging benedikt or maya for when they're back might be a good idea @bmeurer @MayaLekova |
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.
LGTM, just a few minor doubts.
src/node_util.cc
Outdated
Environment* env = Environment::GetCurrent(args); | ||
Local<Context> context = env->context(); | ||
|
||
v8::Local<v8::Object> object = args[0].As<v8::Object>(); |
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.
I couldn't see if we have a check for this in-place. Will we crash if this fails? That said, does it ever really realistically fail?
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.
Yes, it would crash. But this API is only used internally and not exposed. That's why I did not add a safeguard against wrong input values.
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.
I added a check for that as well.
src/node_util.cc
Outdated
->GetPropertyNames(context, v8::KeyCollectionMode::kOwnOnly, | ||
v8::ONLY_ENUMERABLE, | ||
v8::IndexFilter::kSkipIndices) | ||
.ToLocalChecked(); |
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.
Same as above, does this ever fail? Instead, you could try something like
if(!object->GetPropertyNames(...).ToLocal(&properties)) return;
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.
I am not aware about this. I use it as it's done in the V8 tests. @nodejs/v8 do we have to add a guard against this?
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.
I think you do, yes. The whole point of ToLocalChecked
is that you must've checked the value earlier. You could either add a CHECK
statement before this one, in which case it'll still crash (probably in a much better manner, but crash nonetheless) or use ToLocal
as I did above.
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.
Since the original behavior of Object.keys
is to throw if the keys cannot be collected, it makes more sense to return if the maybe is empty and throw in the JS land. (I guess this should fail if you throw an error in the EDIT: nope, it's not in V8 anymore)enumerate
proxy handler, though it is deprecated?
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.
Exactly. Returning (throwing) if the MaybeLocal
is empty seems to be the most logical thing to do. In V8, one would use the macro ASSIGN_RETURN_FAILURE_ON_EXCEPTION
which is essentially:
if (!call(...)->ToLocal(&result) {
DCHECK(isolate->has_pending_exception());
return;
}
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.
Yes, please use @ryzokuken’s suggestion here, I think this could otherwise fail when inspecting Proxies with an ownKeys
handler. A CHECK()
would have the same behaviour as ToLocalChecked()
, so that’s not enough either.
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.
Thanks a lot! I learned something through your comments 👍. It is now handled as suggested.
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.
LGTM once @ryzokuken’s comment is addressed
src/node_util.cc
Outdated
->GetPropertyNames(context, v8::KeyCollectionMode::kOwnOnly, | ||
v8::ONLY_ENUMERABLE, | ||
v8::IndexFilter::kSkipIndices) | ||
.ToLocalChecked(); |
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.
Yes, please use @ryzokuken’s suggestion here, I think this could otherwise fail when inspecting Proxies with an ownKeys
handler. A CHECK()
would have the same behaviour as ToLocalChecked()
, so that’s not enough either.
This significantly improves regular and typed array performance by not checking the indices keys anymore. This can be done with a V8 API that allows to only retrieve the non indices property keys.
32520f6
to
3c83e47
Compare
Rebased. I squashed the reviewed part and kept the other part. |
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.
LGTM, thanks!
This significantly improves regular and typed array performance by not checking the indices keys anymore. This can be done with a V8 API that allows to only retrieve the non indices property keys. PR-URL: nodejs#22197 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Thanks for the reviews! Landed in 3479b1c 🎉 |
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.
LGTM
This significantly improves regular and typed array performance by not checking the indices keys anymore. This can be done with a V8 API that allows to only retrieve the non indices property keys. PR-URL: #22197 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This significantly improves regular and typed array performance by not checking the indices keys anymore. This can be done with a V8 API that allows to only retrieve the non indices property keys. PR-URL: #22197 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This significantly improves the performance of
util.isDeepStrictEqual
andassert.deepStrictEqual
.Update:
I removed a lot of the original optimization. This is now condensed to the new API usage that allows to skip indices. This API is useful for all (typed) arrays. Depending on the input it is a huge performance boost.
These performance improvements are on top of the ones in #22258.
Benchmark
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes