-
Notifications
You must be signed in to change notification settings - Fork 28.3k
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
trees: add diffIdentityProvider for efficient setChildren updates #114237
Conversation
This uses the existing `LcsDiff` diff implementation to generate diff operations when calling `setChildren` on a tree view where the new `diffIdentityProvider` is given. I didn't make this 'default' using the existing identityProvider, since I noticed that (at least) the Explorer view injects different elements in `setChildren` that have the same identity. Previously these would have been replaced, but now they wouldn't. This may be an effect of compressed trees. https://github.com/microsoft/vscode/blob/b6435bc42407d53470e1bc0a0261183148bfde5a/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts#L151-L162 Speaking of compressed trees -- this doesn't work there yet. It looks like compressed trees call setChildren with the parent of the element for whom children are being set... this worked before since the update replaced all previous children, but now the update is not deep. I haven't dug into this yet to find out why this is needed. Performance numbers. This is much faster for the large test tree. Previously each update, by the time all tests were discovered, took about 150ms per tree update: ![](https://memes.peet.io/img/21-01-9cbf70b4-6752-4d0a-82b7-f26bd02db01d.png) Now it's an average of 16.3ms per call, and doesn't take longer for larger trees. Noticably faster to finish and not laggy while it does. ![](https://memes.peet.io/img/21-01-a8d757b8-0529-4067-9d8c-45138d9db7bc.png) We should consider adopting this for all trees if/when we deal with the changed setChildren semantics.
Very cool @connor4312 👏 This looks fantastic at a glance.
Imagine the following compressed tree:
If one calls
But in order to achieve this, we need to change I'm getting second thoughts on the API. I wonder if |
I see. I think the simplest solution there would be a If we give the diffing instructions per call then that would be simple to do :) |
Ok -- updated this to take the diff provider in an argument, and an option to specify update recursion levels. Compressed trees will recurse 2 levels in setChildren calls. |
In a8dd7f6 I noticed that twisties for trees were not updating if they were initially created without children. I think this was hidden by compressed trees due to them recreating from the parent, but this looks like it was a latent bug. I think I recall noticing some cases where twisties were missing, maybe that's what this was... It doesn't look like anyone outside of the tree ever call |
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 really like this API much better! 👏
Description of changes to reference: This PR adds two new options, vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper.ts Lines 107 to 111 in 03dd7bf
Previously, calls to The You can also pass interface IObjectTreeSetChildrenOptions<T, TFilterData> {
/**
* If set, child updates will recurse the given number of levels even if
* items in the splice operation are unchanged. `Infinity` is a valid value.
*/
readonly diffDepth?: number;
/**
* Identity provider used to optimize splice() calls in the IndexTree. If
* this is not present, optimized splicing is not enabled.
*
* Warning: if this is present, calls to `setChildren()` will not replace
* or update nodes if their identity is the same, even if the elements are
* different. For this, you should call `rerender()`.
*/
readonly diffIdentityProvider?: IIdentityProvider<T>; |
@connor4312 minor nit -- but I'd suggest calling |
Tweaked in eba7c23 |
🥳 |
This uses the existing
LcsDiff
diff implementation to generatediff operations when calling
setChildren
on a tree view where the newdiffIdentityProvider
is given. I didn't make this 'default' usingthe existing identityProvider, since I noticed that (at least) the
Explorer view injects different elements in
setChildren
that have thesame identity. Previously these would have been replaced, but now they
wouldn't. This may be an effect of compressed trees.
Speaking of compressed trees -- this doesn't work there yet. It looks
like compressed trees call setChildren with the parent of the element
for whom children are being set... this worked before since the update
replaced all previous children, but now the update is not deep if
identities are the same. I haven't dug into this yet to find out why
this is needed.
vscode/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts
Lines 151 to 162 in b6435bc
Performance numbers. This is much faster for the large test tree.
Previously each update, by the time all tests were discovered, took
about 150ms per tree update:
Now it's an average of 16.3ms per call, and doesn't take longer for
larger trees. Noticably faster to finish and not laggy while it does.
We should consider adopting this for all trees if/when we deal with
the changed setChildren semantics.