How to cache rendered child VNode to avoid calling Child::change on Parent::view?
My app's main bottleneck is the cloning and comparing of props (of one specific component that is instantiated 4 times) that are huge structs and don't change frame to frame.
This is being caused by Child::change being called every time Parent is rendered (at 30 fps, for all 4 instantiations).
Original code in Parent::view: <Child foo=self.foo.clone()/>
I decided to cache the rendered child's VNode and render that, instead of passing the props every time. (I refresh the cached node manually only when foo really changes.)
I tried two approaches:
1.:
// ~155% cpu usage but rendering smoothly. also calls Child::change when Parent renders.
// behavior doesn't differ from non-cached rendering of Child
self.cached_child = html! {
<Child foo=self.foo.clone()/>
};
2.:
// ~105% cpu usage but stuttering, only refreshing about once every second. doesn't call Child::change when Parent renders
self.cached_child = {
let mut r = Child::default();
r.change(child::Props {
foo: self.foo.clone(),
});
r.view()
};
And then both times, in Parent::view I do { self.cached_child.clone() } instead of <Child foo=self.foo.clone()/>:
let dynamic_style = format!(
"transform-origin: {:.4}% center; transform: translateX({:.4}%) scaleX({:.4});",
xpos_percent,
50. - xpos_percent,
self.zoom
);
html! {
<div style=dynamic_style>
{ self.cached_child.clone() }
</div>
}
So it seems only approach 2 is doing what I want (not calling Child::change every time Parent::view is called, not cloning / comparing its foo prop, which is a huge struct) and thus has lower CPU usage.
BUT approach 2 doesn't work: It stutters visually, only updating like once a second.
By updating I mean: The dynamic_style is different every time Parent::view is called, because xpos_percent advances every frame (like in a music player), but with approach 2, it behaves as if dynamic_style is only being updated like once a second instead of at 30 fps, EVEN THOUGH Parent::view is being called!
How can that be? And what's the recommended way to cache a child VNode to avoid calling Child::change when Parent::view is called?