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

Plug-ins leaking CodeLens, etc. #4472

Closed
tsmaeder opened this issue Mar 4, 2019 · 28 comments · Fixed by #7238
Closed

Plug-ins leaking CodeLens, etc. #4472

tsmaeder opened this issue Mar 4, 2019 · 28 comments · Fixed by #7238
Assignees
Labels
bug bugs found in the application plug-in system issues related to the plug-in system vscode issues related to VSCode compatibility

Comments

@tsmaeder
Copy link
Contributor

tsmaeder commented Mar 4, 2019

In packages/plugin-ext/src/plugin/languages/lens.ts, we maintain a cache of CodeLens objects we send to the main Theia process. This is required because the VS Code languageserver-node client library relies on the same object being passed to the "resolveCodeLens" call in order to pass back the "data" field to a language server.
However, this cache is never cleaned up, so we're keeping all CodeLens objects that are ever created.

The same problem seems to exist in task-provider.ts and link-provider.ts.

@tsmaeder tsmaeder added bug bugs found in the application plug-in system issues related to the plug-in system labels Mar 4, 2019
@tsmaeder
Copy link
Contributor Author

tsmaeder commented Mar 4, 2019

For completions, there is a "dispose" method being called when the completion widget is closed, so we are able to clean up the cache when that happens. A cursory inspection has not yielded similar a similar lifecycle event for code lenses. Detecting that a code lens is no longer needed might be a difficult problem.

@tsmaeder
Copy link
Contributor Author

tsmaeder commented Mar 5, 2019

There problem here is tracking when the code lenses are not used anymore in the main Theia process. In the absence of lifecycle events, maybe we can detect liveness by putting them in a WeakMap and regularly checking whether they are collected? Since we are talking about only few objects, we could do so relatively seldom (every 10 secs?)

@tolusha
Copy link
Contributor

tolusha commented Jun 7, 2019

@tsmaeder @akosyakov
VS Code uses IHeapService to collect such objects. So if there are no objections I will create a CQ and copy necessary code.

[1] https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/services/heap/node/heap.ts#L11

@tolusha
Copy link
Contributor

tolusha commented Jun 11, 2019

gc-signals is a native dependency and can be used only at backend. So, I have to find another solution.

@tsmaeder
Copy link
Contributor Author

@tolusha yes, that's why I suggested doing a weak map and purge thingy. The idea would be to have a map object->id and a set and when stuff gets collected from the map, the ids will be in the set, but not the map anymore and you can send "collected" to the back end.

@tolusha
Copy link
Contributor

tolusha commented Jun 11, 2019

@tsmaeder
at first glance it sounds doable, but WeakMap [1] doesn't have any iterable methods over values
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap#Methods

@tolusha
Copy link
Contributor

tolusha commented Jun 11, 2019

@akosyakov @tsmaeder
I have several solutions:

  1. Clean up entities once workpace.onDidCloseTextDocument event is fired.
  2. Clean up entities by timer

@tsmaeder
Copy link
Contributor Author

@tolusha that would work for code lenses, but what about links & tasks?

@tsmaeder
Copy link
Contributor Author

True about WeakMap. How lame!

@akosyakov
Copy link
Member

Clean up entities once workpace.onDidCloseTextDocument event is fired.

It's probably too late, if new code lenses are created on each text change.

Clean up entities by timer

Do you mean to keep WeakMap in languages-main and check which elements were garbage collected by timer?

I wonder can't we just remove them after resolving? Does Monaco try to resolve resolved code lenses again? Could you check?

Also see microsoft/vscode#75048. Seems soon (like in Autumn) there will be dispose method for code lens list on Monaco APIs.

@tsmaeder
Copy link
Contributor Author

@akosyakov Yeah, the idea was to put them in a weak map and check periodically if they have been collected. Problem is that you can't enumerate a WeakMap, so I don't see how we can implement that algorithm. If we could get the "live" code actions from monaco, we could also compute the "collected" set periodically.

I wonder can't we just remove them after resolving?

What about the code lenses that are never resolved?

Good to see that the MS folks are addressing the issue. The question is: can we live with the leakage until then? We should do an estimation of the garbage produced per hour.

@akosyakov
Copy link
Member

Problem is that you can't enumerate a WeakMap

We could keep set of keys identifying code lenses and check periodically whether WeakMap still contains such keys? If not delete a key and release a corresponding code lens in the plugin host.

@tsmaeder
Copy link
Contributor Author

tsmaeder commented Jun 13, 2019

That was my idea, too, but the problem is that the keys are what is weakly referenced in the WeakMap. So in this case, the CodeLens objects. If something is not in the map, how do we know it was there before? We would have to keep a strong reference to it, which would keep it from being garbage collected.

@akosyakov
Copy link
Member

akosyakov commented Jun 13, 2019

Ah, sorry, i did not read WeakMap spec carefully, so code lenses should be a key. When they look useless to us :(

Maybe we can play with provideCodeLenses method itself, i.e. if it is called again for the same document then we dispose old code lenses and provide new. Plus clean everything when the document is closed.

@tsmaeder
Copy link
Contributor Author

Yes, I think that would work. At most, we would have one set of code lenses that are garbage, but not collected per open editor.

@tsmaeder
Copy link
Contributor Author

The same workaround would work for linkProvider

@tsmaeder
Copy link
Contributor Author

I think our implementation of the "taskProvider" API is wrong: https://code.visualstudio.com/api/references/vscode-api#TaskProvider says:

This method will not be called for tasks returned from the above provideTasks method since those tasks are always fully resolved.

This would indicate that we should never call "resolveTask" on a task that is in the object cache in TaskProviderAdapter. So we can just remove the cache there and we're fine for this case.

@tsmaeder
Copy link
Contributor Author

I believe with the above cases covered, we can proceed with this task.

@akosyakov
Copy link
Member

Monaco PR was merged. It should be possible to invalidate caches properly.
Look for TODO in https://github.com/theia-ide/theia/blob/master/packages/plugin-ext/src/main/browser/languages-main.ts
In order to profile the plugin host process follow https://github.com/theia-ide/theia/blob/master/doc/Developing.md#profiling

@akosyakov akosyakov added the vscode issues related to VSCode compatibility label Jan 23, 2020
@vrubezhny
Copy link
Contributor

@akosyakov, @tsmaeder It looks like dispose() (https://github.com/eclipse-theia/theia/blob/master/packages/plugin-ext/src/main/browser/languages-main.ts#L382) is still never invoked for the Document Link Provider. At least it is true for the links generated for *.md-file editor. Also I couldn't find any traces of links clean up in theia/examples/browser/lib/vs/editor/editor.main.js...

Is it OK to clean up the cache every time provideDocumentLinks() or onDidRemoveDocument() is invoked for the Document Link Provider - as we supposed to implement the clean up before the Monaco Upgrade PR was merged?

@akosyakov
Copy link
Member

akosyakov commented Feb 26, 2020

At least it is true for the links generated for *.md-file editor.

How can I get such links?

Is it OK to clean up the cache every time provideDocumentLinks() or onDidRemoveDocument() is invoked for the Document Link Provider - as we supposed to implement the clean up before the Monaco Upgrade PR was merged?

I want to confirm first that we don't overlook it. VS Code relies on it, dispose method is there, maybe we overlook something or don't understand lifecycle of links.

@akosyakov
Copy link
Member

For some reason, they expect dispose method to be on the provider not list of links. Could you check what VS Code does, i.e. how does it register and dispose link providers for the extension host process?

@vrubezhny
Copy link
Contributor

At least it is true for the links generated for *.md-file editor.

How can I get such links?

I'm running my branch (rebased over Theia master) as a Browser Example - and I have defined that dispode() method so it calls according LinkProviderAdapter''s $releaseDocumentLinks()method which should clean the cache. Eclipse Theia is added to my workspace, so, when I open I see that:

  • When I open https://github.com/eclipse-theia/theia/blob/master/CODE_OF_CONDUCT.md I see two Document links added to the cache. (CHANGELOG.md in the same directory gives few hundreds of cached records).
  • When I add edit the document and add a new link to its text - it is also cached
  • When I remove a link from the text - no items removed from the cach (dispose() isn't called)
  • When I close the editor - the cache is not cleared (dispose() isn't called)
  • When I open the same file again - new Document Links are created and cashed, old linka are still in the cache (dispose() isn't called)

@akosyakov
Copy link
Member

akosyakov commented Feb 26, 2020

Links for markdown is not contributed by the plugin system. You should make sure that links are coming from the plugin host process, only then dispose should be called.

@vrubezhny
Copy link
Contributor

vrubezhny commented Feb 26, 2020

Well then I should find another way yo get links,

But then, should we do anything to clear the cache from the links like those for markdown? It looks like they are really never get removed from the cache.

@akosyakov
Copy link
Member

But then, should we do anything to clear the cache from the links like those for markdown? It looks like they are really never get removed from the cache.

I've filed an issue for VS Code to check it. It looks like indeed links are leaking, but it should be fixed in the upstream first. We could try to hack around for the plugin host process, but all other links will leak anyway.

@akosyakov
Copy link
Member

akosyakov commented Feb 26, 2020

It was fixed in the upstream today: microsoft/vscode#91536 (comment) I think it is going to be part of Monaco Feb release. It is important for us not only for the plugin system but fro built-in providers as well.

@vrubezhny
Copy link
Contributor

@akosyakov Thanks!

vrubezhny added a commit to vrubezhny/theia that referenced this issue Feb 27, 2020
Fixes: eclipse-theia#4472

Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
vrubezhny added a commit to vrubezhny/test-storage that referenced this issue Feb 28, 2020
Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
vrubezhny added a commit to vrubezhny/theia that referenced this issue Mar 2, 2020
Fixes: eclipse-theia#4472

Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
akosyakov pushed a commit that referenced this issue Mar 2, 2020
Fixes: #4472

Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
akosyakov pushed a commit that referenced this issue Mar 4, 2020
Fixes: #4472

Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
JesterOrNot pushed a commit to JesterOrNot/theia that referenced this issue Mar 12, 2020
Fixes: eclipse-theia#4472

Signed-off-by: Victor Rubezhny <vrubezhny@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug bugs found in the application plug-in system issues related to the plug-in system vscode issues related to VSCode compatibility
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants