-
Notifications
You must be signed in to change notification settings - Fork 524
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
Improve performance of Wrapper components (Chart, Group, Stack) #1494
Conversation
@dmmulroy It looks like stacks are not working correctly after this change. You can check out the chromatic diffs here: https://www.chromaticqa.com/build?appId=5b4acf7c54c0490024d5980b&number=409 I'm going to dig into the code, too and see if there's something simple missing. |
const nestedChildProps = assign({}, c.props, pick(childProps, sharedProps)); | ||
return React.cloneElement(c, nestedChildProps); | ||
}); | ||
const nestedChildren = React.Children.toArray(child.props.children).map((c) => { |
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.
This is the issue for stacking. The domain won't be correctly calculated if VictoryStack
getChildren
isn't called when calculating the domain, because the y0 / y1 values wont be set on the children. I'm guessing removing this is also where we're getting most of our perf improvements, though. It's probably worth writing a specialized method for calculating a domain for VictoryStack.
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 for looking into this! I'll start poking around to see what I can figure out 👍
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.
Hmm... we also have to make sure that VictoryChart
and VictoryGroup
actually use VictoryStack
's getDomain
method. Maybe it should be a static on that class the same way it is on components like VictoryBar
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'm actually looking into potentially having VictoryChart
and VictoryGroup
properly calculate y0
and y1
in their getCalculatedProps
so we can bank on the those values being available/memoized on subsequent/child getCalculateProps
calls.
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.
Oh, I'm using the wrong terms... I mean _y0
and _y1
. Values that get added to each data point when we stack 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 haven't had a ton of time to spend on this since last week, but I did figure out a small win to fix the regression (I think, still need to check chromatic). It does decrease performance, from 690 milliseconds to about 1.07 seconds, and also increased the number of reduceChildren
from 21 to 771, but that is significantly better than the original 7234 calls.
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.
const nestedChildren = | ||
child.type && isFunction(child.type.getChildren) | ||
child.type && child.type.role === "stack" && isFunction(child.type.getChildren) |
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.
Do we get similar performance improvements without this change?
This is a good idea, but we'll have to be a little careful with that since 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.
@dmmulroy thank you for this improvement. I'm going to merge and release as a patch version today :)
This PR addresses issue #1376.
As soon as the first container component (i.e. Chart, Group, or Stack) renders calls
getCalculatedProps
we effectively have memoized values forcalculatedProps
on all subsequent/childgetCalculatedProps
calls (via the props passed in from a parent component) and we were additionally needlessly callingchild.getChildren
in each iteration oftraverseChildren
in each iteration ofreduceChildren
. EachgetChildren
then calledreduceChildren
(up to four times) and did the same pattern on its children and so on and so forth. So just defaulting the to current childs children (rather than callinggetChildren
) and usingReact.Children.toArray
is enough since we will recurse the whole tree anyways.For the example given in the codesandbox in #1376 I saw an improvement of rendering time from 4.47 seconds to 690 milliseconds and a decrease in calls to
reduceChildren
from 7234 to 21.Benchmarks
Before:
After: