-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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 keyed list ordering issue #1231
Fix keyed list ordering issue #1231
Conversation
Interesting, I'll take a look at this tomorrow. Thanks for diving in! I've been working on updating the Yew example in https://github.com/krausest/js-framework-benchmark and will push a branch that we can do perf testing on |
Benchmarks would be ideal. I will try to write micro-benchmarks if I have time. However, I had an idea of better implementation this morning when hiking (true story xD), I'll try it now. The fix so far is pretty dumb an inefficient. |
@totorigolo I just spent some time reviewing the code and I believe the main issue is how eagerly we call We need a way to move a vnode without calling detach. So I think we need to add a method to vnode allowing us to get a handle on its dom node which would allow us to move it around. Thoughts? |
1a3843c
to
ec0fcbc
Compare
@jstarry I agree that EDIT: Also, what do you think about the other changes, |
Reordering with both vtags and vcomp is... buggy with keyed components 😇 |
Yikes! We should definitely have tests to cover all the combinations. Lists can be keyed as well :) |
I didn't find time today to get the benchmarks setup today. Should be able to get to it tomorrow and can help out on tests if needed |
Here's the branch for updating yew for the JS benchmarks project: https://github.com/jstarry/js-framework-benchmark/tree/yew-update and here's a branch that uses keys (with this PR's fixes): https://github.com/jstarry/js-framework-benchmark/tree/keyed-yew |
be083c8
to
5210c7f
Compare
@jstarry Could you have a look? Manual testing seems to show that the diffing is correct. We definitely need unit tests, but I am too lazy to write them (and also late on a project of mine). Maybe later 😇 Performance-wise, it's ok in some situations and bad in others. This can be visualized by putting breakpoints in Firefox DevTools for insert_before and append_child. Swapping elements is bad for instance. I have ideas to improve this, but I feel that this branch is already too old and I would like to finish this before going into performance fixes. Various ideas for performance wins:
|
5210c7f
to
b0dcc42
Compare
Good call, performance fixes are more fun when you don't have the weight of a huge PR on top. Correctness first, optimization later 👍 |
About the potential memory leak I mentioned, I noticed it in the benchmark "clear rows - clearing a table with 1,000 rows. 8x CPU slowdown", where Yew has terrible results.
Yew 0.7.0 doesn't seem to have this issue though. If anyone wants to confirm this and have a look 🙂 |
😱 |
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.
Good work @totorigolo!
3 main things:
-
I think we should try to avoid needing
VDiffNodePosition::After
andVDiffNodePosition::FirstChild
so that we can cut down on DOM API calls. -
We should make sure we are matching as many keyed list items as we can.
-
Keyed vlists look pretty tricky. Maybe we can remove support for them temporarily?
yew/src/virtual_dom/vnode.rs
Outdated
pub fn reference(&self) -> Option<Node> { | ||
match self { | ||
VNode::VComp(vcomp) => vcomp.node_ref.get(), | ||
VNode::VList(_) => None, |
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.
We are going to have to rethink this since lists can be keyed themselves. Imagine you have a list of keyed lists that need to be re-ordered 😵
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 mitigated the issue, see the last commit (16ffa90). What do you think?
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 not a big fan of the side effect. What if we returned the reference of the first list element here? When the list is empty, it will return the placeholder element
@totorigolo I noticed that |
@jstarry I think that it makes sense for keyed elements. However, this imposes quite a few changes to the current reconciliation algorithm: |
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.
Almost there! I think test organization is going to be really important to make sure we are handling all the edge cases. Could you try following the precedent I set in layout_tests::diff
?
Thanks a lot @jstarry for finishing this! 🙂 |
Thanks a lot for driving this effort, it was great working with you on this @totorigolo! |
Fixes: #1220
I took the opportunity to document the code as I was reading it and trying to understand how it works, and to refactor some bits as well.
For the fix by itself, look for
Reform::Keep if self.key.is_some()
.Still a draft because I would want to investigate performance issues: keyed list feels* slower. To reproduce, just run the new example, add a lot of persons and compare the time it takes to sort the persons when it's keyed or not.
*feels: I tried to measure it using Firefox Performance tab in the Dev Tools, but I cannot find where to read the time a box takes in the JS Flame Chart view.