Skip to content

Use Set() for internal Set backend #1415

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

Merged
merged 3 commits into from
Apr 27, 2018
Merged

Conversation

kanongil
Copy link
Contributor

Along with a isSimpleValue optimisation, this provides a 1000x speedup for the case in #1409.

@kanongil
Copy link
Contributor Author

Actually, this might not be the best way forward, as it seems to slow down the actual validation.

@kanongil
Copy link
Contributor Author

I have updated the PR with another performance patch, which increases the test case validation speed by ~50x compared to the current code.

I'd say this is enough to warrant the optimisation.

Copy link
Collaborator

@Marsup Marsup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is the path I wanted to explore and it looks a lot like what I'd have done. One of the problem I have with this are the for..of though, this translates to horrible things in babel, I can probably take care of that in another commit, however you prefer.

lib/set.js Outdated
return false;
}

const isSimpleValue = !(value instanceof Date) && !(insensitive && typeof value === 'string') && !Buffer.isBuffer(value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be simpler to go directly for a .has test ? I don't think there's any case where it would give false positives if true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's simpler for sure, and should work. It might reduce the performance slightly for some cases, though it will speed up others tremendously. Eg. insensitive string lookup, where it actually matches the case.

I expect it will be a net win.

@Marsup Marsup self-assigned this Feb 2, 2018
@Marsup Marsup added the feature New functionality or improvement label Feb 2, 2018
@kanongil
Copy link
Contributor Author

kanongil commented Feb 6, 2018

FYI I'm looking into a cleaner implementation along with further performance enhancements to the slow path. It's done, but missing a bunch of tests to get 100% coverage.

* Always check if value is found by a simple lookup
* Flags set as "dirty" whenever a ref is added to avoid manual iteration (speed boost when missing value)
* Precomputes non-simple value check to avoid redundant comparisons in iteration
* Only allow refs to contain array items (also a bug fix)
(Buffer.isBuffer(value) && Buffer.isBuffer(item) && value.length === item.length && value.toString('binary') === item.toString('binary'))) {
for (let item of this._set) {
if (checkRef && Ref.isRef(item)) { // Only resolve references if there is a state, otherwise it's a merge
item = item(state.reference || state.parent, options);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The missing coverage is because state.reference is always falsy.

I'm not sure how to add a test that exercises this code. Any ideas?

@kanongil
Copy link
Contributor Author

kanongil commented Feb 6, 2018

I have benchmarked this code a bit, and it seems to perform the same or better (up to ~1000x) in all cases. Both when constructing schemas, and when validating.

@Marsup Marsup added this to the 13.3.0 milestone Apr 27, 2018
@Marsup Marsup merged commit da8d6b8 into hapijs:master Apr 27, 2018
Marsup added a commit that referenced this pull request Apr 27, 2018
@kanongil kanongil mentioned this pull request Oct 17, 2018
@lock
Copy link

lock bot commented Jan 9, 2020

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature New functionality or improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants