-
Notifications
You must be signed in to change notification settings - Fork 793
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
SRTP with large overload sets and errors leads to very high compilation load #9201
Comments
Few hours later, I have submitted a trace (took long, because, well, typing one character takes 20 minutes at least...). I made the trace after: restart computer, removed *.user files, clean solution. I then waited for all background processes to stop (over 30 minutes this time around) and started the trace. The trace collected data for another 35 minutes or so (the time it took to type one character and wait for the again-started background processes to stop and VS to become responsive again). I added comments in the trace for actions I did. The trace is attached to https://developercommunity.visualstudio.com/content/problem/1034777/typing-in-an-f-solution-takes-minutes-to-get-type.html and most likely only viewable to MS employees (@KevinRansom, @dsyme, @cartermp, I assume you are able to access this?). All fun and pun aside, as it is now I cannot develop anything seriously anymore... :S (though, gotta admit, if you type one char per 30 minutes, your code quality greatly improves! As does my coffee addiction). My next steps: disabling everything in VS that could hog the CPU, installing latest previews to see if that improves things etc etc (I severely hope it is some extension I overlooked). Somehow I need to be able to get back to work ;). |
@abelbraaksma I'm looking at the trace, and it's ... weird. I'm not sure if I can say anything at his point, but in the trace, literally nothing is showing as being allocated until 24 minutes into the trace. After that, there's data about allocations. When looking at CPU stacks, it's not until 29 minutes into the trace that anything is registered. This is pending some more investigation, but the CPU and memory usage items actually look fairly normal if I slice the sample to a period where there's actually data. Though it would be indicate of the compiler simply having to process a lot of F# code, since top allocations are from strings and tuples used deep in the guts of the compiler. CPU stacks show a similar story. What's most telling about something being off here is that 1.4GB is nowhere near enough memory usage for devenv.exe to go haywire due to exceeding memory limitations, and 4% CPU is also not a whole lot of work going on. It's almost as if there's some enormous Thread.Sleep() getting called somewhere. |
Ok, bunch of tests further and a bit wiser (and a bit more confused). I did the following things:
I repeated this a few times to be sure. I know that in the past this setting was set to 200 and enabled and that it caused a lot of performance problems. Several issues on github were reported on it and @cartermp (iirc) showed me back then to lower the number to 3 or 4. It has since been 3 and until recently this didn't give me real problems. I thought that if I disabled this option, that tooltips wouldn't work on types that are not defined in the current project, but in a project-to-project reference (at least that is how I remembered it: disabling completely was a bad idea in the past). But I seem to have been wrong, or behavior has changed. I couldn't (yet) find any behavior difference with caching on or off, except for extreme (200-500x) performance degradation. And let's be fair, "caching" suggests speed-up, not speed-down. If you read my reports thus far, I'll summarize the remaining questions:
Until it happens again, I won't be able to get the 40-minutes start-up performance and 20-minutes per-edit performance back, as my actions seem to have changed it, hopefully forever. Hopefully the report, however, can help analyze what happened here and prevent it from happening to others. |
@cartermp, thanks for looking at this! You may read/interpret this wrong (if you got it from the trace), because I could see clearly in Process Explorer that a single thread was running 100% on a single CPU Core. Since I have 24 cores over 2 physical CPUs, that comes down to 4% (since part are virtual cores, sometimes it is reported as 8%). Bottom line: of the list of threads, there was one that was doing all the work, the rest was sitting idly by (I would assume the busy thread was not a background thread, because these should be independent of the rest, but I couldn't verify, they were all
Somehow this doesn't surprise me, as I was also looking live at the CLR traces (again: Process Explorer) and the allocations were very, very low for such a big application and all that CPU. My gut told me there's a wait-loop somewhere and the thing it is waiting on gets released, but only very slowly. And this happens often. This could mean a (semi-) race-condition, a file on disk that is shared and not released properly, a memory mapped file, mutex etc etc. Though I don't think it is caused by something in memory (well, not from the start). The behavior survived restarts of the computer, updates of Windows and basically over a week of doing all sorts of stuff. Only until I disabled (not removed) all extensions, the behavior changed (to 2-4 minutes). This behavior is reproducible with my current code and settings. The previous behavior isn't. I've read online that there were some issues with Live Share. I am not using it, not even logged in, but the extension was enabled. Could the extreme delay been caused by waiting on network services or even a log-in that never happened and has to time out several times? |
@abelbraaksma , can you share some details of the project/solution that you have loaded. Does it have a lot of projects or is it a single project? Is it netsdk or dotnet framework project? Is it on github somewhere that we can load? Thanks Kevin |
@KevinRansom, I can certainly share the project in confidence, or we can set up a remote call with shared screens if that helps (it is mostly closed source, but they won't be too fuzzy sharing it under conditions). The solution I tested this with and used for the trace has 11 projects. Since I had issues with performance in F# long before as well, I have split the "big solution" into a bunch of smaller ones, depending on what part I am working on. I rarely work on my The main solution has 34 projects (not all of which are very significant). I've estimated the LOC at some 150k lines, but depending on how you count you may find a different number. All projects are (unf.) still legacy projects. There was something in the new project format that blocked me from changing (we tried), atm. I can't remember what that was. However, there aren't any really fancy things going on: each project is .NET Framework 4.6.1 (we build libraries and cannot update to latest all the time), each compiles to a library, three compile to an EXE. There is a handful of C# projects, but these are comparatively small. There are two "heavy" projects: lots of source lines, quite a bit of SRTP-style inline (but again, nothing out of the ordinary, I think) and compiled binary size of all builds up to ~13MB Release Build (only counting DLLs, not counting test projects). Those 2 "heavy" projects are 5.5MB and 2.7MB resp. after compilation. A clean build takes around 2-3 min (dep. on whether or not tests are included) on my system. I think this all counts as "big" but not "huge" or "extreme". Another C# project I manage has 110 projects in the main solution, with 10 min clean build time. |
Well looky here: 26% of CPU time in the sample is spent checking if a file exists. Ooof. I'm still not quite confidence in the trace data I'm looking at since there's such a massive gap of time before there's anything going on here. However, the data I'm looking at doesn't look abormal. So I'm not terribly surprised with what I'm seeing, especially if your codebase makes use of a lot of assembly references @abelbraaksma |
Does it use typeproviders? And I would really appreciate if you could remember what blocked the conversion, because we are no longer shipping legacy project format templates. They will still load and edit, but we don't really want new projects created using that format if we can avoid it. |
I know. But this project has been in development for > 7 years, and has some MSBuild dependencies baked in. I'm sure it can all be converted eventually and we really should. But we spent a few days trying and gave up. It is not a trivial conversion (and so much even MS admits on the pages dedicated to moving over to the new format). But there's a big upside with conversion that we certainly recognize: multi-targeting. Currently, that's a mess and we really want to target .NET Framework and .NET Core (reason: customers ask for it), which currently isn't easy to do.
Nope, none. There are some quotations though (test prj with UnQuote). |
So ... perfectly straightforward medium sized solution ide goes super slow .... eek. Did you ever see this type of behaviour with our oss VisualFSharp solution ? |
@abelbraaksma Regarding in-memory cross-project references: when the number of projects held in the cache is only 3 (which is small) and there are a lot of project references, this can actually lead to more memory and CPU consumption over time since the IDE is constantly recomputing things u necessarily. I'd be curious about your experience if you turned it back on and then set the value to something high like 200. |
@cartermp If so much time is spent there, and there's probably IO involved which doesn't show in the CPU trace, that can surmount together as "was virtually doing nothing" for a long time, right? This suggests that it was looking for a file that wasn't there, was corrupted or otherwise time-consuming to retrieve. Since the whole performance changed dramatically after I changed the extensions (disable, re-enable), I doubt it is the extensions themselves that cause the strange performance, but what if (thinking out of the box) the MS extensions share a file with (binary) settings that in turn cause this file-checking to go so slow? Btw, the full ist of assemblies include a bunch of System.XXX, FParsec, Netwonsoft, NodaTime, FSharp.Core. The majority being System, which is a lot of files, but only 3.3MB. |
PS: since we're all online debating this, would it perhaps be more efficient to set up a call?
@cartermp I don't understand this, because:
Which begs the question, how can it spent so much CPU time in that method if there aren't that many files to load? Or: these files it tries to load have nothing to do with F# or my project? Some inner process going berserk? ;) |
@abelbraaksma phillip was referring to the trace .. your experience is actually scary. |
ah, got it! 👍 Yep, it was scary indeed ;). So scary it got funny, and then scary again :P |
@cartermp, how can I access my own trace? I'm quite good at performance analytics, maybe I spot something. If you guys wanna call or chat, my Skype handle is the same as my name here, but a dot between first and last name. Or any other app, or actual phone, is also fine. |
Hmm, but that suggests that I wouldn't be able to see mouse-overs of types, modules, functions from cross-project refs? I verified this, and I can see everything, even if I haven't done a build (if the option is switched off). When on, well, tooltips appear after minutes at start-up or after an edit.
I'll try this |
@KevinRansom Rectification on LOC. The F# part of the traced solution had ~126,500 non-empty lines in But still within the bounds of "medium sized" or what I like to call "rather big" solution ;).
Not so extreme, no. Though that solution generally behaves a bit slower than my own in regular code-editing stuff. But since 90% of my time is spent in my own project and I've only occasionally done editing in the OSS VisualFSharp solution, it is not a fair comparison. I've seen extreme degradation before a few times (though not as extreme as these days). It usually happened when there were a lot of errors, i.e., there's a type I basically use everywhere. Change that type, and the there'll be thousands of errors. Try then to edit something at the far end in the solution, this is dead slow. But that is not typical, and since I split the solution in smaller sub-solutions, such large refactorings are now done in phases. In this case, there are 10 errors spread over two or three files. But even without the errors, it was dead slow. |
@abelbraaksma I cleaned, built and loaded the OSS solution in vs, rebuilt. And still I am not seeing classification and tooltips. classification is the phase that shows the cyan TypeNames. CPU is doing little to no work, Working set is 766,000 K so ... really not stressed. |
@KevinRansom this call is the one where all of the CPU time is being spent checking if a file exists: https://github.com/dotnet/fsharp/blob/master/src/fsharp/CompileOps.fs#L3013 The Is it necessary to have that exists call in there, given that we're already wrapping this in a Let's not discuss the F# OSS solution in this thread. The issues seen here don't surface in our codebase after the numerous times we've profiled this one. |
@cartermp throwing an exception is hugely more expensive than checking a file exists. So this call would be way more expensive if we relied on the exception. The exception exists for cases where the reason the file is inaccessible has nothing to do with its presence. For example permissions to access the file is not granted. |
Right, but was that ever measured? That is, have we measured how expensive it is to do these things when a file doesn't exist is relative to the time spent checking if it exists (an expensive operation on Windows)? |
@cartermp: you may be on to something (CPU time, not wall-clock time):
Note: with the setting disabled, initial startup is 7 sec (after first screen appears), and 2 sec before mouseover work, almost no delay whatsoever between edits. So I'm still not getting the "caching" bit and why the mouseover should wait for the background task to finish if the info is already there (the "stale" setting is enabled). I think something operates in the wrong order here. |
@cartermp Can I access my own trace somehow? I'd like to see what you see
Perhaps it makes sense to create a "clean" trace, because the extreme situation has not re-appeared and I suspect the cause is really in some kind of deadlock that may not readily show in the CPU-bound or memory-bound traces. A new trace would reveal perhaps why, with "caching" enabled, it is still so slow, or, even if we accept that it can be slow, what is causing it and warn users against using such settings-combinations. |
I'd also be interested in why these background processes appear to mostly act synchronously, as I keep seeing one thread doing all the work. Also: even when doing nothing (like when typing this), not having focus on VS IDE and background tasks finished, devenv.exe still spins at 100% for a single thread (1 core at 100%, 8% overall). |
Ok, my last comment may point to what @cartermp was already hinting at: (almost) nothing is happening. Meaning, if, when doing nothing, the CPU slice it takes is 9%, and when running background tasks it is also 9%, the difference is so small that my money is on some rogue thread that blocks the rest from running efficiently. Is there a way I can detect this thread is the UI thread or something else? Notice the cycles delta for 16108, this one is consistently on top (when I do nothing in the IDE). Again, 8% here means 100% on a single CPU core. |
Strike that, sorry for the noise. It makes no sense. I just tried the theory, but the hogging thread above, 16108, disappears completely (ends) when I edit something, ergo, it cannot be the UI thread. While editing, it shows a more logical slicing. Though it is beyond me why the numbers don't spread over the different cores and together add up to something closing to 100% when it's busy. There seems to be too much waiting-between-threads going on: |
The massive wait times with nothing going on smells like race condition or deadlock or something going on in the VS process. F# does use multiple threads, but only for operations that rely strictly on parse data. It could be that we're messing with something else here, but I've never observed this with daily usage of VS in lots of F# codebases...VS threading, on the other hand, is immensely complicated and there's a lot of stuff happening outside of F# all the time in the VS process. So my intuition is that there's a bug somewhere else, but I couldn't say way. Regarding this:
Tooltips rely on typechecked information, and due to the design of the F# compiler service and the nature of type inference, requests for that data are serialized and placed in a queue. This could be made a lot better in theory, but it'd be a huge amount of work. |
@cartermp That sounds like how I remember it, but there are two things that don't add up, or I don't understand them:
Here's how I think it works:
And that's the thing: the behavior described here happens when I edit something in one file, in the top-project. It still appears to rebuild everything (the 3 min delay), as opposed to using stale data (I haven't seen this setting working, ever), or simply using the cached file (after all, there was no change in referenced projects). If you need to rebuild all each time anyway, the caching-option Also somewhat surprising: clean + rebuild all takes less time than waiting for tooltips to appear. I'd expect the other way around, since optimizations don't have to kick in.
yeah, my intuition was leaning that way too, alas... ;) |
Here is some code, it grabs a bunch of files, and then for each of them checks if it exists. I have two different commented out lines of code.
So, this first result is for an outer loop of 100 loops of exceptions: This second result is for FindFile: Lets increase the outer loop to 175000 |
Checking ETW events for If that's true, I need to change my reporting strategy. @sharwell, do you know more about this perhaps? It feels a bit like the same way PerfMon works and by default only shows 2 min CPU history and never more. |
The traces are recorded in a circular buffer. When the buffer runs out of room, old events are discarded to make room for new. Since there are multiple buffers involved internally, the phenomenon might not happen at exactly one point in time - each event type and view might start showing data at a different time in the trace. |
Based on all the new information, and since the VS IDE kept hanging on closing the IDE, I did:
I then made a 1 min trace, which is reported here: https://developercommunity.visualstudio.com/content/problem/1041761/same-as-before-hanging-on-closing-vs-ide-with-an-f.html (still uploading, looking at the tcp/ip traffic). @sharwell, @cartermp, @KevinRansom I hope this new trace allows to do a more to the point analysis, as it rules out extensions this time. The hanging does suggests, to me at least, that the cause may not be solely F# related. |
We'll want to dig into this one, assuming I'm reading it right. That's nearly 12GB of allocations in 97.5 seconds, coming from 112.3k calls to AddConstraint, It's also 87% of all CPU time in the sample: I'm thinking something is horribly wrong, since that is an absurd amount of allocations and CPU time. |
When the project cache is set lower than the amount of projects than you actually have and have Enable in-memory cross-project references turned on, you will experience cache thrashing and it will tank everything. Per target framework is considered one project, therefore one project with 3 TFMs is like three projects and in VS, everytime you type it will try to update the three versions of the project at one time which can slow things down. Honestly, we should just stop allowing anyone to set this number when in-memory cross projects turned on, it simply does not work and has not worked ever. |
ATM the extreme behavior happens to all solutions except one, making it, unf., impossible to work. I may also have found something else that appears to be related to the coloring, tooltips etc coming very, very late. I left it on overnight and found this:
When I checked other occurrences of that event, there was one at 15 May, 2020 (the date I first reported this issue). Note that it says "the process was terminated", but it doesn't say which process. Devenv.exe is still running a.t.m. I apologize for not checking the event viewer sooner. However, this error seems to appear only after the very long waiting for coloring to appear finishes. In most cases I've killed the process long before that, which is probably why I only see this error 7 times since 19 April, 2020. What is still very hard to understand is that I've seen both the good and bad behavior with exactly the same code. Otherwise I'd assume some combination of code causes an exponential performance curve. @TIHan, that seems right, and was also @cartermp's suggestion: to set the number of cached projects to 200. The total amount of projects is somewhere between 9 and 20 for most solutions I work on. Maybe we can simply hide the setting, or add some warning text like "experimental". Iirc, it was once introduced in a time with VS 2017 or so that F# tooling regularly caused VS to run out of memory. That's not the case so much anymore. I'm going to clear everything, update everything that wasn't updated yet, restart and re-enable/re-disable the extensions. Earlier on that caused the VS IDE to behave normally again. |
@cartermp: To rule out some possible causes, I've tried the following things
After each step, I reopened one or more of the troubling solutions. While a few days ago, disabling extensions removed the issue, whether or not there was an error in the code, today, each and every attempt results in the same behavior:
What I haven't tried yet:
Bottom line: I'm now totally locked out of developing :S. |
FINALLY!!!!!! @KevinRansom, @cartermp, @sharwell, @TIHan: I have a repro, and a likely cause, see attached zip. It is possibly not as simple as it could be, but at least it is down to 2 files, a few hundred same-looking lines in a project with no dependencies other than that of a default project. It only took three days to get down to this abomination of a repro :D. Apologies it isn't smaller. Detailed instructions are in the solution in
Now you have two scenarios:
An alternative is to do the opposite. Fix the lines by commenting them out. Close (or force-close) the IDE. Reopen the solution. Recreate the error lines (by removing the comments and the The deliberately wrong function is the following (the observed behavior can be seen with many other "errors while typing", this was just the easiest to repro): The messagebox shown and not disappearing when closing IDE should be the following: The cause of this erratic behavior of the IDE and the F# compiler lies in the second file, I've observed while refactoring this that from time to time I needed to make My guess: something is operating on O(2^n) or worse the minute certain parts cannot be resolved in the SRTP code, and it keeps on looking or something, but won't find a resolution for the (edit 2020-05-28: new upload is a bit cleaner, removes a warming and removes a bunch of lines that didn't add up to the erratic behavior) I would appreciate it if someone could try the repro on their machine. Even though I can observe the behavior on at least two machines with two different OS's and basically all versions of VS since 2017, it is very well possible that a faster machine does not lock up, or only spins for a few min instead of hours. In that case, you may artificially add even more PS: it should be stressed that this looks like "extreme" code, but that's just what I had to do to get down to a repro. I do have code like PPS: originally, the behavior reported in my OP shows that after some time the IDE comes back, it just gets really, really slow. My gut tells me that happens just before a possible O(2^n) or O(n!) operation can still be finished before the end of times. Add one more case that adds to the exponential behavior, and what took 40 minutes can become 40 years. PPPS: if I wait 3h, 30min (CPU time), using the zip provided here, the devenv.exe process calms down and I can close the IDE normally without it locking up. So, whatever loop is causing this, it halts eventually. |
This reproduces on my system. For me VS becomes unresponsive after commenting the three lines. |
@cartermp, @KevinRansom, @TIHan: if I remove the SRTP part, as in the attached ZIP, the system remains responsive and acts normal. Though the SRTP is very straightforward (only one function with a method constraint), and each use is typed, meaning there shouldn't be a need for an The constrained resolution should show a linear performance characteristic here, which in this code (see For comparison, same code without SRTP, that does not lead to an IDE lockup is here: (please do not mistake this for a workaround, it is only in this simple repro that I can fix the code. In real-world code I cannot just remove all SRTP) @charlesroddie, many thanks for trying the repro. I hope to see more confirmations from others as well, or better yet, a hint as to what causes this :). |
@cartermp, @KevinRansom, sorry to bug you again, I know you guys are very busy, but I'm still blocked from normal development and need help to continue. Could you take a look, please? See my comment from two weeks ago. It would already help me a lot if someone is able to say "put a breakpoint there and there and then try this and that", or "the cause is likely here in the source", then I know where to look further. |
I'm really not surprised 300 overloads of Why are you coding it like this? It's been known for a long time (ever since SRTP was implemented - 15 years) that there are limitations on performance for the mechanism, and that very large overload sets are going to be an issue. This has been discussed many times (and some attempts in F# 4.x to shortcut performance bottlenecks caused incinsistencies in the core resolution mechanism). You should not use SRTP like this until performance is known to be suitable for such large overload sets. If we do any work on this, it would only be as part of or additive to #6805, which incorporated very careful testing for some applications of constraint resolution. And even if we fixed this particular issue immediately, it seems very likely you are going to hit other similar problems. In either case you should not use SRTP over 300 overloads on your critical coding path, and unblock yourself by removing your use of it. In particular avoid maximally generic, multi-variate SRTP like this:
I modified your code to remove the use of SRTP simply by changing to an explicit call to https://gist.github.com/dsyme/9606cd38002295eb7ff1f28c3155df80 |
@dsyme, I know that using SRTP like this might cause issues. But that's not relevant:
The problem may well be with SRTP, also in my original solution there's SRTP, if not only because I use F# core library functions. But the behavior is not sound, SRTP or not. It compiles and resolved fine, and if an error occurs upstream, it sometimes prevents further processing of anything. I don't think this is a performance issue that needs fixing, but a bug that somehow should stop doing whatever it's doing when there's an incomplete let binding present. It goes from few sec type inference resolution, to 2.5hr when there's, in the same code, a single error. That just can't be right, SRTP or not. And that doesn't disappear when you fix the error, and it locks VS from closing. No code should be able to do that. After restart of VS you still won't be able to continue. If you don't have a backup, you're out of luck. Best you can do is rollback your code in your source control and lose your work. Again, no code, however bad, should have that effect. Btw, I've encountered the issue of VS becoming unresponsive in code that didn't have SRTP down stream. I know that doesn't mean it's the same thing, but I do know that from the best of my reflection, this kind of behavior just happens from time to time (few times a day). Ingredients for this happening: large code base, frequent editing, somewhere a typo.
Tx, I did that too, and provided the contrarepro as well in my penultimate comment. |
Yes, it would be good if it was stable in the presence of introduced errors. However if there are errors then there are almost certainly more unresolved type inference variables floating around the code, and this will mean method overload resolution of SRTP will not succeed. This could cause a dramatic difference in such a case. In other words, the slow resolution of SRTP over very large overload sets might only manifest itself when errors are introduced. I'll think over whether there's any way to make this stable, and it would be good to test it in the context of #6805. But the "just don't do this" guidance is definitely still in place. |
I understand, but there are sometimes no other ways to code something, unless you want boxing or RTTI. Neither are ideal, and SRTP is being used both in FSC as in many libraries, code examples and real-world projects. Perhaps you mean "don't use double-lookup SRTP" (or whatever the I was also under the mistaken impression that local inline functions with SRTP have less this problem than global ones. That seems not to be the case, it doesn't matter whether it is in scope or not. I've no problem with optimizing code to please the compiler, or in this case, to please the IDE. I'd rather not, but that's what it is. But since I have no idea what kind of code can crash the IDE, I just code and don't expect the worst (generally). So I searched around and found that there are let inline (!>) (x:^a) : ^b = ((^a or ^b) : (static member op_Explicit: ^a -> ^b) x) and a few others. In the "full solution" I've no idea which of them will cause issues, but I can certainly refactor some of them:
It's certainly "dramatic" ;). It's just so weird that you can code for many hours like a breeze, but then suddenly everything freezes, and you've no idea how you got there (Ctrl-Z won't help, because, you know: frozen). @dsyme, Anyway, thanks for looking into this, but I would like to ask if you can give me a little guidance of where I should look for fixing this. I'm not sure I can, but I would like to try, as I am not the first with a "hanging VS" and I won't be the last, whether it's SRTP or not. I would love to try to fix it, though I'm aware it may be an uphill climb. |
Let's call it double-barrelled SRTP. I'd say for master today large is ~30 witnesses for double-barrelled SRTP once one of ^a or ^b is known. Double-barrelled SRTP is used in FSharp.Core for op_Addition etc., but in most applications of SRTP the number of witnesses narrows down quickly once ^a or ^b is known. In your case it remains at ~300 until both are known. However there is no hard-and-fast rule and you should always be wary of non-standard uses of SRTP (i.e. things beyond the patterns we use in FSharp.Core). Fundamentally if you are using SRTP like this then you are doing type level programming. The compile-time operational characteristics of such programming always matter and people using things will always push things to the limits, just as they do in any other kind of programming. (We see the same thing with long compile-times of C++ template code, for example, or long resolutions for Haskell type classes to complex calculations in the type system - people will always drive things to the max). For any system offering anything like this there will be limits. |
Looking at this again. I'd like to emphasise this: you should always be wary of non-standard uses of SRTP (i.e. things beyond the patterns we use in FSharp.Core and TaskBuilder.fs). SRTP is crucial for F# in many ways, for overloaded arithmetic. However, if pushed too far (double-barrel, cascading constraints, large overload sets) it becomes a fragile and subtle mechanism w.r.t. performance, error messages and some corner-case glitches in resolution. People are pushing it to limits that are falling off one or more of these cliffs. Just don't push the limits with SRTP. It's not worth it. |
I'm closing this as to some extent it's expected behaviour, per my comment here: #9201 (comment) |
EDIT (22 May): A repro that exhibits the likely cause of this bug (albeit not exactly the described sluggish behavior), was finally found by me after a week or so and 70+ helpful comments and traces. Instead of reading all, new visitors should probably just go to #9201 (comment). Please try the repro, I'm very curious whether it's reproducible.
A project that takes roughly 1 min to compile, after loading it in VS 2019, I first compiled it and then decided to measure how long it took for coloring, tooltips etc appear:
GIF animation of first 30-something minutes, click to start from the beginning, and grab some crisps and 3 beers before you start ;).
Repro steps
Reproducible with my project and possibly with other large projects, I'd be interested if others have seen similar behavior.
At 34 minutes, it showed 22 tasks in background queue
At 53 minutes, it showed 19 tasks in background queue
At 56 minutes, it showed 0 tasks (finished) and mouseovers were responsive again (until I edit anything, one letter took another 5+ minutes with 6 tasks in queue ...).
Expected behavior
While I can understand that building up the IDE can take a bit longer than a simple rebuild-all, I don't expect it to take the same time I'd normally tend to fall asleep in a Vin Diesel movie. Making the screen-capture was just about similarly entertaining ;).
Actual behavior
As described above. Slooooow. For fair comparison, I opened only one VS IDE, and disabled most, but not all, 3rd party extensions.
In the Task Manager I can see devenv.exe at 4% CPU, which is effectively one CPU core on my machine. Memory for devenv.exe in those 40+ minutes went from 1.4GB to 1.6GB. Traditionally, I only notice extreme sluggishness after it reaches 2.8GB or higher.
Known workarounds
Strangely, I don't always see this behavior, though it has been like this for a few weeks now. I'm now going to restart, remove any auxiliary files, clean everything and start afresh, see if it still happens. As it is now, it is absolutely unworkable.
Related information
I'd be very interested in getting to the bottom of this, if you need any traces (I assume you do) or anything else, I'm more than willing to provide those.
The text was updated successfully, but these errors were encountered: