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

Visual Studio should use the concurrent GC to minimize UI thread freezes #15924

Closed
vasily-kirichenko opened this issue Dec 15, 2016 · 23 comments
Closed
Assignees
Labels
Area-External Tenet-Performance Regression in measured performance of the product from goals.

Comments

@vasily-kirichenko
Copy link

vasily-kirichenko commented Dec 15, 2016

I encounter huge UI freezes while triggering autocomplete in F# code. It turns out they were caused by blocking GC:

image

Here we see a 28 seconds (!) freeze, i.e. autocompele appeared after 28 seconds delay, all this time entire Visual Studio is unresponsive.

Turning on the concurrent GC like this:

...<runtime><gcConcurrent enabled="true" />...</runtime>

in C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\devenv.exe.config

makes things a lot better:

image

Here we have ~2 seconds freeze as a maximum.

I understand it's a VS configuration issue, not Roslyn, but VS is not open sourced and I don't know where I should create this issue.

/cc @forki @dsyme

@benaadams
Copy link
Member

@vasily-kirichenko Can also try Help->Send feedback->Suggestion (or Bug) in VS

@rojepp
Copy link

rojepp commented Dec 15, 2016

@benaadams Then no-one else could follow along! :)

@vasily-kirichenko
Copy link
Author

The only thing that makes me nervous is that MSDN says the concurrent GC is always turn on by default, see https://msdn.microsoft.com/en-us/library/yhwwzef8%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

@isaacabraham
Copy link

@vasily-kirichenko that's a great spot, and I don't want to sound picky here :-) But is 2 seconds what we can realistically expect from F# intellisense in VS (based on your experience so far)?

@forki
Copy link

forki commented Dec 15, 2016

@isaacabraham tbf it is on NameResolution.fs in the compiler. That is a huge file/project and even in VS2015 it's not faster. Also with dotnet/fsharp#1825 in place we won't longer block the UI thread. This is good progress for shitty situation. But we definetely need the gc switch. Otherwise battle is completely lost.

Also take a look at dotnet/fsharp#2018 - this should help to reduce the work a bit and make things faster. Unfortunately it seens noone in Redmond is working on such things.

@isaacabraham
Copy link

That's fine - I don't mind that at all, as long as we're not talking (more) big regressions from VS2015 :-)

@cartermp
Copy link
Contributor

Tagging @Pilchie for more info.

@Pilchie
Copy link
Member

Pilchie commented Dec 15, 2016

Tagging @pharring and @Maoni0 (Though Maoni at least is on vacation right now) - we did a lot of investigations of different GC modes during the VS 2015 cycle precisely to try to reduce long GC pauses while typing, etc. Additionally, VS normally sets the "Sustained low-latency" mode during typing. If something is causing a 28 second blocking GC, I'd be very concerned about what is allocating enough during typing to trigger that.

@Pilchie Pilchie added Area-External Tenet-Performance Regression in measured performance of the product from goals. labels Dec 15, 2016
@Pilchie Pilchie self-assigned this Dec 15, 2016
@pharring
Copy link
Contributor

As @Pilchie says, Roslyn uses sustained low latency mode for most typing operations. See http://source.roslyn.io/#Microsoft.VisualStudio.LanguageServices/Implementation/GCManager.cs,af6b4206e05a381b,references

Note that F# is not Roslyn, though.

Also, as @vasily-kirichenko pointed out, concurrent GC is already the default - or at least it should be. It's tough to prove without ETW traces, and I mean no disrespect, but I suspect there is some placebo effect with making that configuration tweak. (IIRC, for example, that GC mode is actually configured in devenv's CLR hosting module and the .exe.config setting is ignored). An ETW trace (use PerfView) will tell us for sure the actual GC mode. Note that, even with concurrent GC enabled, you can still get some pretty long Gen 2 blocking GCs. That's why, after all this time, the most effective tactic for improving responsiveness (reducing GC delays) is to reduce allocations.

@forki
Copy link

forki commented Dec 15, 2016

Note that F# is not Roslyn, though.

@pharring F# in VS2017 RC is ON Roslyn.

@forki
Copy link

forki commented Dec 15, 2016

If something is causing a 28 second blocking GC, I'd be very concerned about what is allocating enough during typing to trigger that.

@Pilchie good, we are all concerned. So does that mean that MS is finally assigning some people on this? ;-)

@vasily-kirichenko
Copy link
Author

@pharring Yes, F# uses Microsoft.CodeAnalysis.XXX to plug into VS, for example that's how we do autocomplete https://github.com/Microsoft/visualfsharp/blob/master/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs#L198

Am I right that all this GC tuning stuff http://source.roslyn.io/#Microsoft.VisualStudio.LanguageServices/Implementation/AbstractOleCommandTarget.Execute.cs,308 is executed for F# as well?

@vasily-kirichenko
Copy link
Author

That's why, after all this time, the most effective tactic for improving responsiveness (reducing GC delays) is to reduce allocations.

Yes, of course you are right, but it's basically F# compiler that allocates a lot and it's unlikely anybody is gonna investigate and fix this, so we need a way to deal with it.

@pharring how can I deduce from ETW results that the concurrent GC is actually running? With the server GC it's simple - we have number of cores heaps and number of cores GC threads. Any points on this?

@KevinRansom
Copy link
Member

@forki
Paul is including the Roslyn C# and VB compilers and language services neither of which play a role in the F# integration.

@forki
Copy link

forki commented Dec 15, 2016

yeah I guess the term "Roslyn" is used a bit ambiguous

@KevinRansom
Copy link
Member

I also expect that now that we have the IDE integration in place, we will be able to be a be more organized in trying to improve the F# compiler service performance. Although I expect we may need to implement a bunch of performance telemetry so that we can start to rigorously collect data.

@pharring
Copy link
Contributor

@forki Thanks for the info on F# in 2017. I didn't know that. My excuse is that I moved off the Roslyn team a little over a year ago and VS 2015 was mentioned a couple of times above.

@vasily-kirichenko In PerfView you can look at the GC stats view for the "CLR Startup Flags" settings. Here's a snippet:

GC Stats for Process 18728: devenv
•CommandLine: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"
•Runtime Version: V 4.0.30319.0
•CLR Startup Flags: CONCURRENT_GC, LOADER_OPTIMIZATION_MULTI_DOMAIN, DISABLE_COMMITTHREADSTACK
•Total CPU Time: 210 msec
•Total GC CPU Time: 0 msec

Also, I checked the CLR hosting code in devenv and, indeed, the GC mode is set in startup flags and not via the .exe.config.

@vasily-kirichenko
Copy link
Author

That's what it looks like in dotTrace:

image

Looks rather concurrent :)

@vasily-kirichenko
Copy link
Author

GC Stats for for Process 6960: devenv
 •CommandLine: "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\devenv.exe" 
•Runtime Version: V 4.0.30319.0
•CLR Startup Flags: CONCURRENT_GC, LOADER_OPTIMIZATION_MULTI_DOMAIN, DISABLE_COMMITTHREADSTACK
...

@pharring
Copy link
Contributor

Recommend: Close this issue with no further action. Concurrent GC is already the default mode for both VS 2015 and VS 2017.

@forki
Copy link

forki commented Dec 15, 2016

I trust @vasily-kirichenko's test, but that placebo effect is really high. For me switching this on actually felt like I huge performance win. I didn't notice 20s+ freezes anymore. Everything feels nearly instant now. Is this pure luck?

@brettfo
Copy link
Member

brettfo commented Dec 15, 2016

For what it's worth I confirmed @vasily-kirichenko's hunch by setting and hitting a breakpoint at the line he highlighted while typing in an F# file.

@Maoni0
Copy link
Member

Maoni0 commented Jan 6, 2017

@vasily-kirichenko I just got back from vacation. 2 things seemed concerning to me and I am not sure if there was conclusions on them (I have to admit I did not read this thread fully so if I missed anything, my apologies in advance). 1) the huge blocking GC pause is odd, did you happen to do some investigation to see why it was that long? 2) why concurrent GC was not enabled when it's the default for VS. If you wouldn't mind providing info on those it would be much appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-External Tenet-Performance Regression in measured performance of the product from goals.
Projects
None yet
Development

No branches or pull requests