-
Notifications
You must be signed in to change notification settings - Fork 419
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
Analyzing projects is extremely slow compared to MSBuild or Visual Studio #2241
Comments
Just to add my 2cents to this, I am experiencing exactly the same issue with a .NET 5 solution. Have been trying various things over literally the last year or so to improve the situation to no avail. Have tried:
I did try running strace at one stage against the mono instance but I'm not familiar with linux internals to figure out whats going on. This is all whilst running latest inside both WSL2 and a remote SSH (both Ubuntu 20.04) instances. EDIT: Just to add - this is not a slight to omnisharp and the team, its an amazing piece of kit and VSCode is an absolute game changer. If this performance issue and a handful of other stability bugs could be fixed it would literally be perfect. |
One thing that affects this is Roslyn Analyzers. To disable them you could try this in
It is not ideal, but at least that makes the projects load much faster |
@seesharper Right, but Roslyn Analysers are active in VS too and I want them active for a reason. Disabling them is not a solution. |
From just observing the effects it seems like VS / MSBuild run all the analyzers at the same time in one pass but OmniSharp maybe runs them one at a time or maybe one file at a time instead of the whole project at once? This could perhaps explain the enormous performance difference. |
Agreed, it is really not a solution. When it comes to actually analyzing the projects I think Omnisharp just forwards this to the Roslyn libraries. Maybe it is the communication between OmniSharp and Vs Code that slows things down. I don't know. Just a thought |
I'm convinced that its some kind of interaction between omnisharp, mono and probably the solution/libraries I'm building. I've tried previously to build a smaller test solution (since I can't share my commercial source) to no avail. I'm thinking that if I can catch it spinning at 100% CPU and capture logs/straces then that might be of help to someone more knowledgeable than myself? |
A year or two ago I tried to do some performance tracing with dotTrace but I didn't really know what to look for. I remember could see that it was the analyzers back then too. It must be possible to run them more efficiently somehow. Maybe Microsoft developers from the Roslyn project can help? They should be interested in making C# development experience great even in VS Code. |
Just to illustrate the problem - this is a screengrab from btop. I've just restarted VSCode about 10 minutes ago - and after a period of multicore usage (which would be fine) the usage settles down into mono alone continuously pegging at least one core to 100%. Its this behaviour that then basically never goes away. Running
|
@kieranbenton There is actually a version of OmniSharp that runs without mono. The code is in the https://github.com/OmniSharp/omnisharp-roslyn/tree/feature/omnisharp-vnext branch. You'll have to compile it yourself, but it might be an interesting experiment to see if similar problems occur when running on dotnet |
I'm on Windows but I tried the .NET 5 build on a smaller project at home:
I can try it on the bigger project at work tomorrow and maybe see if it ever finishes. |
For comparison, on the same project at home, running |
I wasn't able to use the .NET 5 OmniSharp at work because it's a .NET Framework project. I tried the .NET Framework v4.7.2 one in the |
Ok, can I summarise and get some clarity here please? @DavidZidar are you saying your work project is a .NET Framework v4.7.2 project - and so you have to use the 'normal' mono Omnisharp build in order to interact with that? And that the I don't understand @DavidZidar what you mean by "I tried the .NET Framework v4.7.2 one in the feature/omnisharp-vnext branch but it does not seem any better." since that seems counter to that branch being .NET 5 based? If that is the case, then I will try and build vnext and run with that for a bit and report back. |
@kieranbenton |
There is also a task to publish a Mono build in that branch which is confusing. Can you explain further @seesharper ? |
@DavidZidar I don't work on this repo, but my guess is that the |
Any idea how you get the vscode omnisharp extension to load Omnisharp using .NET 5 instead of mono? After overriding my "omnisharp.path" I'm getting...
|
@kieranbenton Maybe try adding |
Ok, I've got that working now - thanks to some help on the slack channel. FYI, you need to configure it as follows:
First report is that I believe that is significantly better. I've restarted a few times this morning and after an initial surge of the analyzers obviously kicking in every time its reached steady state of 0% CPU after about 5 minutes. I'll keep running like this for this week and report back. |
I don't know this code base but I attached dotTrace using timeline view and recorded 20 seconds of churn, it doesn't look great. If I interpret what I'm seeing there seems to be a shared text writer that is blocking everything almost all the time so the analyzers are effectively running one at a time instead of in parallel. |
I tried letting the analyzers just go until completion at work and it took just over 20 minutes to do what MSBuild does in 40 seconds. |
I just had a little time to actually look in the code and the problem was not at all what I thought but rather more simple. The problem is foreach-loops, like this one in particular (but I found 6 such loops): Lines 245 to 250 in 1521fca
Which means it really is only analyzing one document at a time. I tried replacing the above with this quick hack and now the analysis is actually using more of my cores and complete much faster: await Task.WhenAll(documentsGroupedByProject.Select(async documentId =>
{
var document = project.GetDocument(documentId);
var diagnostics = await AnalyzeDocument(project, allAnalyzers, compilation, workspaceAnalyzerOptions, document);
UpdateCurrentDiagnostics(project, document, diagnostics);
})); That's probably too parallel though, it would be better to limit the amount being done to n number of threads where n might be the number of cores on the system. The new |
Great work @DavidZidar! Definitely the new Out of interest, are you actually interested in analyzers running for the whole solution? I would much prefer if they would just run 'on demand' for the currently opened files. Otherwise even with making those code paths parallel, for a decently sized solution thats going to absolutely clobber multiple cores -> 100% until the whole solution is complete. In some ways only clobbering a single core is actually preferable to me at least... (can't believe I'm saying that). |
@kieranbenton Ideally it should be a toggle or a setting. Personally I prefer the whole solution to be analyzed, it's all to easy to miss warnings in files that aren't currently open when refactoring code. Also, I've got 16 cores, I want to put them to work. :) |
Strong agree fwiw. I've always found it very impractical that when I do manual refactoring in VS Code, I have to either force a full reanalysis or do a build to find out what broke. Would love to have a toggle for full solution analysis. |
i've made an implementation that seems to work nicely for my machine it defaults to using half of the available cores, but allows configuration with a new key in in my testing on a pretty large c# solution (32 projects) it is a lot quicker than it used to be and spins up the number of cores i configure it to. |
isn't this analyze-only-open-files what the foreground worker does? #1507 if that is correct - then what you are asking for could essentially be an option to turn off the background worker, and just do the foreground analysis? |
@TomasEkeli yes, that sounds bang on - am I correct in assuming there is no way to turn off the background worker right now? My workflow is effectively run a full project analyze once after I add a new analyzer - do any wide ranging cleanup for results I deem important enough to tackle up front, then crank the rest down to informational and fix as I work on individual files as part of other work. Avoiding the 5 mins of 100% CPU on VSCode startup (even now after the vnext branch has landed - which seems much more stable) would be great. |
can i suggest registering a new issue for that? i like the suggestion |
I took a stab at this also in #2312, building upon the excellent work by @TomasEkeli in #2285 but with some further improvements. |
Thanks everyone that worked on this, it will help a lot! But seeing how this issue was closed entirely I have to say it doesn't really solve the underlying problem, OmniSharp is still using several times more processing power to do the same thing that MSBuild and Visual Studio do with much less. Using more cores is a good step on the way though! |
Ominisharp is still brutally slow for me and really flaky. The solution in question has 25 projects in it. Even when I tell it to only analyze open files, it still takes forever to analyze and even when done, it takes forever to autocomplete. VS.net is immediate on both accounts. What's the solution for this? |
I'm not sure there is a solution currently, it's just a constant pain. If only Microsoft could take VS Code seriously and rewrite OmniSharp and use the Roslyn API efficiently in the same way that Visual Studio does, that would be something. |
that would be nice, but i doubt they will - the recent hot-reload kerfuffle showed that microsoft are still aiming to make visual-studio the better experience. |
I am working on a .NET Framework-project where a full build using all .NET 5 SDK analyzers takes about 40 seconds, Visual Studio can analyze the project in a similar amount of time.
OmniSharp on the other hand can analyze for hours on end and use many gigabytes of RAM. In fact, it never gets done because as I work things change so one CPU core is running hot all day long. I just had to kill the OmniSharp process because it was using 21 GB of RAM.
I have noticed this performance difference in other projects too, even in pure .NET Core projects. This has been the status quo for years.
So there seems to be a fundamental difference in how analysis is done in OmniSharp vs regular Roslyn since there is at least an order of magnitude or more difference in speed.
Would it be possible to involve Microsoft to get this properly fixed once and for all?
The text was updated successfully, but these errors were encountered: