-
Notifications
You must be signed in to change notification settings - Fork 18
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
removeChild is super-slow #37
Comments
... I wonder if we could use |
We might consider running |
For the record, I tried (around line 357 of var removeFn = function () {
var parent = nodes[0].parentNode;
for (var i = nodes.length - 1; i >= 0; --i) {
ko.cleanNode(nodes[i]);
parent.removeChild(nodes[i]);
}
}; It appears to be marginally faster (having cut out some function calls), but remains a third of the recalculation. I would expect |
Well. That's unexpected: Rendering faster by hiding DOM elements instead of removing them (Or at least it would've been until I started looking into this problem)
I wonder if that's an effective strategy for us. We could also make the removal lazy (and power-friendly with |
@brianmhunt in your implementation, now that you are iterating via a decrement, be careful with array holes. |
Thanks @krnlde – We construct the Do you perceive a risk here based on a use case? If so, do you have any suggestions on how best to deal with them? Thanks & Cheers |
The best way to deal with holes is utilizing I'm not too much into the code to know whether there will be holes at any time. Edit: as Axel quotes you could also use the In your code this would look like this: for (var key in nodes) {
ko.cleanNode(nodes[key]);
parent.removeChild(nodes[key]);
} if you need to start right, you'll need to reverse the array first: for (var key in nodes.reverse()) {
ko.cleanNode(nodes[key]);
parent.removeChild(nodes[key]);
} (untested) |
Hiding the nodes and then removing them on next queue flush may improve the situation. But I don't know, can't get into it right now more deeply but as I'm thinking it should be faster to remove hidden elements because no need to reflow. On the other hand I don't know how other libraries can be faster, aren't they using the same native |
@cervengoc I rooted through React and Angular and didn't see any references to The only alternative to |
Also take into account: having a loose DomNode which is not appended elsewhere that could catch all the removed DomNodes for a while by Btw: So does react: https://github.com/facebook/react/blob/master/src/renderers/dom/client/utils/DOMChildrenOperations.js#L120 |
Thanks @krnlde – Great finds re. the I think it's definitely worth checking out the performance of a batch-move (to a DOM node with |
@brianmhunt Due to a desired super-optimization I started re-reading this thread too. What exactly do you mean by "lazy-remove"? I'll try to implement it if we get to a good idea. |
Thanks @cervengoc Lazy-remove would be, at its most basic, a two-step process:
Theoretically this would break up the browser work into two separate loads. One would need to experiment though. Another option that may help is to remove all the DOM nodes from the document (or clone them, but then one would have to re-apply bindings), manipulate them, then re-insert them. That'd be problematic for very large lists, but in the average case might be faster. Possibly. Not sure. :) Another optimization (and I'm getting really derailed here), when a list is made to be empty, we could write a shortcut that empties all the DOM nodes in a much faster cycle. |
Here's a patch for the current brianmhunt/knockout-fast-foreach that does just that: https://gist.github.com/AllSeeingEye/b25b338ebf76131ff5e128aa8c43505e Updates are now made with the same speed as initial array deployment. |
I've given it a try (though I admit my implementation was pretty naive), and it didn't bring any noticeable improvements. Hiding the nodes + deleting inside animateFrame + clustering fixes things. |
For no reason apparent to me,
removeNode
is painfully slow in the following test: Performance Comparison for React, Angular and Knockout.Look at this:
And here, you can see that
removeChild
is taking over 22% of the time:In that same profile,
appendChild
takes 0.33% of the processing time.I'm not sure how we can optimize
removeNode
, but something's definitely awry.The text was updated successfully, but these errors were encountered: