Skip to content
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

fix(customPropTypes): improve perf of suggest #2314

Merged
merged 1 commit into from
Nov 25, 2017

Conversation

dvdzkwsk
Copy link
Member

@dvdzkwsk dvdzkwsk commented Nov 13, 2017

This is not ready yet because it's not solving the case presented by #2301, which concerns word ordering.

Word ordering has been solved by way of key sorting.

'Invalid argument supplied to suggest, expected an instance of array.',
` See \`${propName}\` prop in \`${componentName}\`.`,
].join(''))
throw new Error('Invalid argument supplied to suggest, expected an instance of array.')
Copy link
Member Author

Choose a reason for hiding this comment

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

We don't need to perform this isArray check every time the component is checked, since it's only used to initially define prop types. Given my current change we lose some information about which property was specified incorrectly, but the benefit is that if it is used improperly it will throw immediately.

// skip if prop is undefined or is included in the suggestions
if (_.isNil(propValue) || propValue === false || _.includes(propValue, suggestions)) return
// Convert the suggestions list into
const suggestionsLookup = suggestions.reduce((acc, key) => {
Copy link
Member Author

Choose a reason for hiding this comment

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

Convert O(n) lookup to O(1).

Copy link
Member

Choose a reason for hiding this comment

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

🙌

@dvdzkwsk dvdzkwsk force-pushed the chore/suggest-perf branch 2 times, most recently from 5711d29 to ee79375 Compare November 13, 2017 15:27
@codecov-io
Copy link

codecov-io commented Nov 13, 2017

Codecov Report

Merging #2314 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2314   +/-   ##
=======================================
  Coverage   99.73%   99.73%           
=======================================
  Files         152      152           
  Lines        2655     2655           
=======================================
  Hits         2648     2648           
  Misses          7        7

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a2dfbad...85d36f0. Read the comment docs.

// skip if prop is undefined or is included in the suggestions
if (_.isNil(propValue) || propValue === false || _.includes(propValue, suggestions)) return
/* eslint-disable max-nested-callbacks */
const findBestSuggestions = _.memoize((str) => {
Copy link
Member Author

@dvdzkwsk dvdzkwsk Nov 19, 2017

Choose a reason for hiding this comment

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

Implementation is the same, just passed the base string in instead of an array so that _.memoize can actually do its job, since arrays are not memoized by value:

let calls = 0
const fn = _.memoize((arr) => ++calls)

fn(['my', 'words'])
fn(['my', 'words'])
console.log(calls) // 2

Note that the previous usage of this memoized function was incorrect, since it would ignore the second argument suggestions, meaning the first call to it with a given propValue would have won out. This was unintentionally mitigated by the fact that _.memoize only tracks the first argument by default, and that argument was an array, ergo no actual memoization was occurring.

The real fix would be to write our own resolver function for the memoization, but it would essentially achieve the same thing as I'm doing here by inlining the function, given the use case for this suggest utility.

// way of looking up a value in the map, i.e. we can sort the words in the
// incoming propValue and look that up without having to check all permutations.
const suggestionsLookup = suggestions.reduce((acc, key) => {
acc[key.split(' ').sort().join(' ')] = true
Copy link
Member Author

Choose a reason for hiding this comment

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

Key sorting

@dvdzkwsk
Copy link
Member Author

Anything else needed here?

@layershifter
Copy link
Member

@davezuko I want to hear @levithomason before merge this. Let's wait for his review.

@levithomason levithomason merged commit 52087e3 into master Nov 25, 2017
@levithomason levithomason deleted the chore/suggest-perf branch November 25, 2017 17:17
@levithomason
Copy link
Member

I had a few conversations with @davezuko over Slack about this. It should make a pretty big improvement. Actual metrics would be nice, but I don't have time for it. Will release soon.

@levithomason
Copy link
Member

Released in [email protected]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants