Skip to content

Conversation

@jeffkl
Copy link
Contributor

@jeffkl jeffkl commented Feb 26, 2024

Bug

Fixes: NuGet/Home#9041

Regression? Last working version:

Description

@KirillOsenkov recently helped us out and mentioned that the linked issue is of great importance to his current efforts. This change specifies the readOnly flag to the DependencyGraphSpec constructor indicating that the objects it contains do not need to be cloned. I added this constructor for static graph-based restore but didn't add it to regular restore so this change makes them the same.

I added an overload to prevent a breaking API change even though I doubt anyone would be affected. The existing constructor just keeps the existing behavior.

PR Checklist

  • PR has a meaningful title

  • PR has a linked issue.

  • Described changes

  • Tests

    • Automated tests added
    • OR
    • Test exception - Existing test coverage will suffice
    • OR
    • N/A
  • Documentation

    • Documentation PR or issue filled
    • OR
    • N/A

@jeffkl jeffkl self-assigned this Feb 26, 2024
@jeffkl jeffkl requested a review from a team as a code owner February 26, 2024 22:17
Copy link
Member

@nkolev92 nkolev92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm comfortable with changing the behavior of the API altogether if it's only called from the CLI.

fwiw, I really thought we were already doing this in both static graph and standard restore.

/// Creates a <see cref="DependencyGraphSpec" /> from the specified MSBuild items.
/// </summary>
/// <param name="items">An <see cref="IEnumerable{T}" /> of <see cref="IMSBuildItem" /> objects representing the MSBuild items gathered for restore.</param>
public static DependencyGraphSpec GetDependencySpec(IEnumerable<IMSBuildItem> items)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to make this the default?

It's only used in CLI scenarios right?
It's VS where mutation is a concern correct?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me why VS would need to mutate a DGSpec. If projects are loaded/unloaded, a new DGSpec can be created with the new project list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also like a better understanding of why the items in the DG spec are cloned?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The readonly part can be a bit misleading.
Readonly means that the PackageSpec is not cloned.

The primary reason around package spec cloning is defensiveness. In Visual Studio as a long lived process, the PackageSpec is not guaranteed to be immutable.

After this, we're down to 2 clones, 1 in the RestoreRunner, 1 in the CPSPackageReferenceProject, the latter one is needed, but the previous I'm 99% sure we don't need anymore.

Long term the approach should be;

  1. Introduce a PackageSpec lock mechanism, and the dg spec would only accept locked PackageSpec. Then it can just avoid cloning.

@nkolev92
Copy link
Member

@jeffkl Should this "close" the issue it's linked?

Given that we're not fixing the VS side, I think that issue should remain open.

@jeffkl
Copy link
Contributor Author

jeffkl commented Feb 27, 2024

@jeffkl Should this "close" the issue it's linked?

Given that we're not fixing the VS side, I think that issue should remain open.

I almost opened a new issue but hesitated because I don't think we'll ever "fix" the Visual Studio side of things since it needs to mutate the dgspec right? The person who opened the original issue really only cares about command-line based restore at the moment so I figured this pull request would fix the issue and if we wanted we could open a new one for Visual Studio restores? Or I can open a new one for command-line based restores? I do not have a strong opinion.

@jeffkl
Copy link
Contributor Author

jeffkl commented Feb 27, 2024

I've opened NuGet/Home#13270 as a way of tracking the removal of the cloning in Visual Studio code paths.

@jeffkl jeffkl merged commit 806adae into dev Feb 29, 2024
@jeffkl jeffkl deleted the dev-jeffkl-cmd-restore-no-clone branch February 29, 2024 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Restore: excessive deep cloning of ProjectSpec

4 participants