Skip to content
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

User data provider should not iterate over raw changes #126660

Closed
bpasero opened this issue Jun 18, 2021 · 11 comments · Fixed by #139793
Closed

User data provider should not iterate over raw changes #126660

bpasero opened this issue Jun 18, 2021 · 11 comments · Fixed by #139793
Assignees
Labels
debt Code quality issues file-watcher File watcher insiders-released Patch has been released in VS Code Insiders perf
Milestone

Comments

@bpasero
Copy link
Member

bpasero commented Jun 18, 2021

Looking at perf traces from #124723 I noticed how quite a bit of time can be spend here:

private handleFileChanges(changes: readonly IFileChange[]): void {

And I was wondering how it is possible that you can access the raw file changes until I noticed how you actually listen to the raw events here:

this._register(this.fileSystemProvider.onDidChangeFile(e => this.handleFileChanges(e)));

But doing so bypasses all our logic in the file service, e.g. to produce a ternary search tree for paths from the FileChangesEvent. I am also considering to add some debouncing logic for the processing of these raw events in case thousands of events are fired in short period of time. I cannot do this on the level of the provider though because that is API.

Can we please revisit that and see if the code would benefit from operating directly on FileChangesEvent? It provides powerful methods like contains and affects that can be used to lookup with a resource.

@bpasero bpasero added debt Code quality issues perf labels Jun 18, 2021
@sandy081 sandy081 added this to the July 2021 milestone Jun 18, 2021
@bpasero bpasero added the file-watcher File watcher label Jun 21, 2021
@sandy081 sandy081 modified the milestones: July 2021, August 2021 Jul 28, 2021
@sandy081 sandy081 modified the milestones: August 2021, September 2021 Aug 23, 2021
@sandy081
Copy link
Member

@bpasero I can definitely debounce the listener. But I am not sure if I can avoid iterating because, currently I am filtering for user data resources and map them to user data scheme. I can skip the filter and just do mapping.

@bpasero
Copy link
Member Author

bpasero commented Sep 24, 2021

@sandy081 remind me again why the FileUserDataProvider needs to depend on the local fileSystemProvider? Can you not use IFileService.onDidChangeFile simply to listen to changes?

@sandy081
Copy link
Member

I use vscode-userdata scheme for user data resources (settings, keybindings...) which needs to have a FSP registered for this scheme. FileUserDataProvider is just a wrapper on top of local fileSystemProvider that is just forwarding calls and events by changing the scheme.

@bpasero
Copy link
Member Author

bpasero commented Sep 24, 2021

Could you listen to the changes via IFileService method and look at the scheme being file to do the same thing instead of listening to the events of the provider? You can then emit the events from your provider after having listened. Would just have to make sure that you are not ending up in an endless loop (i.e. when you emit events, ignore file changes from the file service).

@sandy081
Copy link
Member

I think I can actually remove this FileUserDataProvider because it is used only in Desktop and I can use local file scheme and local filesystemprovider.

@bpasero
Copy link
Member Author

bpasero commented Sep 24, 2021

👏

@sandy081
Copy link
Member

I am using userdata scheme in Web and using the same in Desktop is providing good abstraction in the code. We check at various places in code for this scheme and handle things differently just like file scheme, for eg undo. If you think this change is worth that it improves perf efficiently, I would remove it. Otherwise I would focus on following improvements:

  • Debouncing the event listening

Could you listen to the changes via IFileService method and look at the scheme being file to do the same thing instead of listening to the events of the provider?

Not sure how this is different from what I am doing now ?

@bpasero
Copy link
Member Author

bpasero commented Sep 27, 2021

Not sure how this is different from what I am doing now ?

The file service has logic to debounce when spam occurs, so we do not fall into the trap of reacting to thousands of events:

private static readonly FILE_EVENTS_THROTTLING = {
maxChangesChunkSize: 500 as const, // number of changes we process per interval
maxChangesBufferSize: 30000 as const, // total number of changes we are willing to buffer in memory
coolDownDelay: 200 as const, // rest for 100ms before processing next events
warningscounter: 0 // keep track how many warnings we showed to reduce log spam
};

@sandy081
Copy link
Member

Could you listen to the changes via IFileService method and look at the scheme being file to do the same thing instead of listening to the events of the provider? You can then emit the events from your provider after having listened.

It seems FileChangesEvent does not have access to changes for me to iterate and trigger change event on the resources I care.

@bpasero
Copy link
Member Author

bpasero commented Sep 27, 2021

There is:

/**
* @deprecated use the `contains` or `affects` method to efficiently find
* out if the event relates to a given resource. these methods ensure:
* - that there is no expensive lookup needed (by using a `TernarySearchTree`)
* - correctly handles `FileChangeType.DELETED` events
*/
get rawAdded(): TernarySearchTree<URI, IFileChange> | undefined { return this.added; }
/**
* @deprecated use the `contains` or `affects` method to efficiently find
* out if the event relates to a given resource. these methods ensure:
* - that there is no expensive lookup needed (by using a `TernarySearchTree`)
* - correctly handles `FileChangeType.DELETED` events
*/
get rawDeleted(): TernarySearchTree<URI, IFileChange> | undefined { return this.deleted; }

We can add rawUpdated back.

@bpasero
Copy link
Member Author

bpasero commented Dec 27, 2021

See #139793

@github-actions github-actions bot locked and limited conversation to collaborators Feb 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
debt Code quality issues file-watcher File watcher insiders-released Patch has been released in VS Code Insiders perf
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants
@bpasero @sandy081 and others