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

High CPU when target framework is empty #3670

Closed
davkean opened this issue Jun 26, 2018 · 33 comments
Closed

High CPU when target framework is empty #3670

davkean opened this issue Jun 26, 2018 · 33 comments
Assignees
Labels
Feature-Dependency-Node "Dependencies" node in Solution Explorer that display project, binary & package references Tenet-Performance This issue affects the "Performance" tenet. Triage-Approved Reviewed and prioritized
Milestone

Comments

@davkean
Copy link
Member

davkean commented Jun 26, 2018

Opening the following projects causes VS to constantly consume CPU:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework></TargetFramework>
  </PropertyGroup>

</Project>

or

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks></TargetFrameworks>
  </PropertyGroup>

</Project>

Design time builds are constantly occurring in the background.

Also hit by #3489 by AWS SDK.

@davkean davkean added Bug Tenet-Performance This issue affects the "Performance" tenet. labels Jun 26, 2018
@davkean davkean changed the title Visual Studio constantly consumes CPU if you open a project with an empty target framework (dependency node) Visual Studio constantly consumes CPU if you open a project with an empty target framework Jun 26, 2018
@davkean davkean added the Feature-Dependency-Node "Dependencies" node in Solution Explorer that display project, binary & package references label Jun 26, 2018
@davkean
Copy link
Member Author

davkean commented Jun 26, 2018

Pretty sure this is dependency node.

This was hit by an MVP.

@Pilchie
Copy link
Member

Pilchie commented Jun 26, 2018

@davkean did you look at all? Is this an infinite restore loop?

@jmarolf
Copy link
Contributor

jmarolf commented Jun 26, 2018

just tried this scenario. Its infinite restore.

@Pilchie Pilchie added this to the 16.0 milestone Jun 26, 2018
@davkean
Copy link
Member Author

davkean commented Jun 26, 2018

It didn't look like infinite restore - it was infinite design-time builds but that will likely be dependency node reinitializing over and over.

@Pilchie
Copy link
Member

Pilchie commented Jun 27, 2018

Oh, right - dupe of #3489 then?

@davkean
Copy link
Member Author

davkean commented Jun 27, 2018

Yep, dup'd it against this one.

@eerhardt
Copy link
Member

eerhardt commented Jul 5, 2018

I'm hitting this in dotnet/corefx after updating the .csproj's to SDK-style projects.

To repro:

  1. pull https://github.com/wtgodbe/corefx/tree/SdkProj (the branch from PR Convert all projects to SDK-style corefx#29831).
  2. Build once from the root of the repo on the commandline: build.cmd
  3. Open src\System.Collections\System.Collections.sln.

However, in my scenario I don't see any design-time builds continually happening using the Build Logging window. However, it is consuming a lot of CPU:

image

@Pilchie
Copy link
Member

Pilchie commented Jul 6, 2018

Can you collect an ETL trace during this period? https://github.com/dotnet/roslyn/wiki/Recording-performance-traces-with-PerfView

@eerhardt
Copy link
Member

eerhardt commented Jul 6, 2018

Yes, I'll get it tomorrow morning.

@eerhardt
Copy link
Member

eerhardt commented Jul 6, 2018

I took 2 traces.

  1. With the solution already loaded, and eating CPU in the background, I ran the trace for about 10 seconds.
  2. A full trace of loading VS, loading the solution, and then letting it run for ~30 seconds.

I uploaded them to the internal scratch file share: \\scratch2\scratch\eerhardt

@Pilchie
Copy link
Member

Pilchie commented Jul 8, 2018

@sharwell and/or @davkean - care to take a look?

@davkean
Copy link
Member Author

davkean commented Jul 9, 2018

@eerhardt Can you verify that you have a TargetFramework to verify if its just another symptom of that? This is slated for 16.0, so won't look at until then if its a dupe.

@eerhardt
Copy link
Member

eerhardt commented Jul 9, 2018

Yes, setting TargetFramework makes the CPU usage drop down to nothing when VS is in the background.

The only behavior difference I noticed from the originally described issue is:

Design time builds are constantly occurring in the background.

I wasn't seeing any design-time builds happening in the Build Logging window.

@davkean
Copy link
Member Author

davkean commented Jul 10, 2018

Thanks.

It might be good to sync up on CoreFx's requirements and why you can't use TargetFrameworks/TargetFramework. I've had your situation in the back of my mind, and want to address it and make it work for you out of the box.

@eerhardt
Copy link
Member

Agreed. @weshaggard would have the best background knowledge.

I haven't completely ruled out that we can't use TargetFrameworks/TargetFramework yet. We are setting TargetFramework to workaround this issue. It's just that it is kind of a meaningless concept in the corefx repo's projects. In "normal" projects, it defines which version of netcoreapp/netstandard/netfx you want to reference. In corefx, we aren't referencing a framework. Instead, we are defining the framework.

@davkean
Copy link
Member Author

davkean commented Jul 10, 2018

Think of "TargetFramework" as simply another open-ended dimension at which you can specialize a configuration like Platform and Configuration, except it's treated slightly different:

  • We build all of them by default
  • We provide IntelliSense for all of them

You can call your target frameworks "foo" and "bar" if you'd want (assuming you fill in the details, TargetFrameworkIdentifier, TargetFrameworkVersion, etc that we produce from the friendly name)

@weshaggard
Copy link
Member

Aren't there other assumptions made about those properties as well? For example doesn't Nuget interpret them?

@davkean
Copy link
Member Author

davkean commented Jul 11, 2018

Barring bugs, TargetFramework is supposed to be treated as a "user value". NuGet gets the full TFM that we auto-generate from TargetFramework, and is supposed to be only using TargetFramework in conditions within the generated props files.

@davkean
Copy link
Member Author

davkean commented Jul 11, 2018

My ultimate aim is to be able to able to specialize on other things; such as RID. It would be helpful if we could feed your requirements in so that what we develop around this works for you and you can stop working around MSBuild/VS

@clairernovotny
Copy link

You can call your target frameworks "foo" and "bar" if you'd want (assuming you fill in the details, TargetFrameworkIdentifier, TargetFrameworkVersion, etc that we produce from the friendly name)

This actually won't work because of NuGet validations. When I initially tried to implement multi-RID builds, I attempted it by using/abusing TFM's like netstandard2.0+win-x86. I had to monkey-patch a lot of targets to make it work despite setting NuGetTarketMoniker, TargetFrameworkIdentifier and TargetFrameworkVersion correctly. NuGet just blew up with unsupported/unknown TFM's.

@clairernovotny
Copy link

My ultimate aim is to be able to able to specialize on other things; such as RID. It would be helpful if we could feed your requirements in so that what we develop around this works for you and you can stop working around MSBuild/VS

I made this work today by making the outer loop get the RID's for the TFM and pass that into the inner loop:
https://github.com/onovotny/MSBuildSdkExtras/blob/db55a020a7d7d0d7119ff01c3104a9dd62a51f11/Source/MSBuild.Sdk.Extras/Build/RIDs.targets#L23

It works and builds, in VS and the command-line, but the project system/IDE knows nothing about it. So no IntelliSense for that combination (to catch the define's for each RID).

@davkean
Copy link
Member Author

davkean commented Jul 11, 2018

It's not supposed to be interpreting that value, at least that was the original design - but there's going to be bugs here. I'm rewriting/removing our usage of TFM at the moment, and then I'll start pushing on other teams.

@clairernovotny
Copy link

clairernovotny commented Jul 11, 2018

@davkean it most certainly is interpreting/validating TFM's. Check out this horror for my first attempt at using TFM+RID:
novotnyllc/MSBuildSdkExtras#93

I had to rewrite the items that NuGet saw to remove the +RID and then it generated the props/targets incorrectly, so I needed to read its file and find/replace the source TFM with the TFM+RID to make props/targets work correctly.

What I have in that PR is functional, just a lot grosser than the solution based on a discussion with @jeffkl.

@clairernovotny
Copy link

Here's where NuGet Restore (at least) is validating the tfm itself:

https://github.com/NuGet/NuGet.Client/blob/b82a7274e5f58c8af2eb052b8ff98d3d29fed66e/src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/SpecValidationUtility.cs#L131

I would expect that it should be based on a NuGetTargetMoniker value, so I can define my own TFM and say "use netstandard2.0" for it. No dice today.

@nguerrera
Copy link
Contributor

We did fully intend for TargetFramework do be open ended, but there are definitely issues. Another place where there's a problem is where we negotiate tfms between project references. It passes the TargetFrameworks to nuget to pick the "nearest" one. It would be prohibitively expensive to get all of the full tfms there in the current design. And even if we could there would cases where you have the same full TFM for different custom TF. I think the only out would be to require such P2Ps to skip the negotiation and manually assign the desired TF. There are bugs around doing that though, IIRC.

@davkean
Copy link
Member Author

davkean commented Jul 11, 2018

It passes the TargetFrameworks to nuget to pick the "nearest" one.

Ah, yeah, forgot about this case - we'd need the same translation logic in the outer build, or call into the inner build - which would be expensive.

@clairernovotny
Copy link

@davkean @nguerrera do either of you know off hand where this logic lives in the targets? Would save me some spelunking time.

@nguerrera
Copy link
Contributor

Related: NuGet/Home#5154

@jjmew jjmew added the Triage-Approved Reviewed and prioritized label Jan 17, 2019
@jjmew jjmew modified the milestones: 16.0, 16.X Feb 13, 2019
@drewnoakes drewnoakes changed the title Visual Studio constantly consumes CPU if you open a project with an empty target framework High CPU when target framework is empty Jul 18, 2019
@davkean davkean assigned ocallesp and unassigned jmarolf Dec 4, 2019
@davkean
Copy link
Member Author

davkean commented Dec 4, 2019

@ocallesp This is likely the cause: #3670 (comment).

@davkean
Copy link
Member Author

davkean commented Dec 4, 2019

Have a look inside AggregateCrossTargetProjectContext where it persists the targetfamework.

@davkean davkean added this to the 16.5 milestone Dec 4, 2019
@drewnoakes
Copy link
Member

@ocallesp feel free to reach out if you would like to discuss this.

@ocallesp
Copy link
Contributor

@davkean this issue is only reproducible in VS 2017. Not able to repro in VS 2019/master.

@drewnoakes drewnoakes removed the Bug label Oct 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature-Dependency-Node "Dependencies" node in Solution Explorer that display project, binary & package references Tenet-Performance This issue affects the "Performance" tenet. Triage-Approved Reviewed and prioritized
Projects
None yet
Development

No branches or pull requests

10 participants