perf(getUnhandledProps): replace lodash with vanilla js #860
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #859
TL;DR Conclusion at the bottom.
As with the linked issue, I've also noticed some severe performance issues, mostly in Grid and Grid column. It appears there is a memory leak somewhere in getUnhandledProps due to lodash.
Calculating unhandled props can be expensive due to the several nested object references it has to traverse to first calculate the handled props:
autoControlledProps
,defaultProps
keys,props
keys. It then needs to loop the props again to omit all those keys. This can be done several times per render, per element. This alone should not be responsible for the results we're seeing below, however.This PR replaces lodash with vanilla JS, resulting in >12,000 times performance improvement .
It also caches handledProps so they are only calculated once per component (handled props never change). This will be fixed permanently once #731 is merged as we'll have a static array of handled props baked into every component.
Rough Perf Analysis
No cache, lodash (baseline)
After lots of testing, I notice that the Grid and Grid column render times seem increase every render for the particular view I am testing against. Note the instance count and render count remains constant, but the time required is growing rapidly.
First Render -
1s
Second Render -
3s
Third Render -
27s
With cache, lodash
First Render -
1.5s
Second Render -
21s
Third Render -
1.3s
Additional tests...
I found the
21s
odd here, so I ran renders 4 and 5 with results of3.6s
and2.8s
. This seems odd.No cache, vanilla JS
All three runs completed in <=2ms (approx.) 😮. This certainly means, lodash is at fault here.
Cache and vanilla JS
Using vanilla JS is obviously sufficient, however, I tested vanilla with cache for completeness. The results were not significantly different from vanilla JS without cache.
Conclusion
Something in lodash is extremely non-performant given the usage in our
getUnhandledProps()
lib method. Using vanilla JS increases performance by up to >12,000 times. Caching makes no difference and is not necessary.