-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support lazy instantiation of ProjectInstance values when CPS Evaluat…
…ion cache is used (#10030) ### Context This PR targets the specific scenario of constructing a ProjectInstance object from the evaluation data stored in CPS's evaluation cache, with the goal of saving memory and execution time during Solution Load. In a previous change (2a789cd), I modified the ProjectInstance logic to rely on virtualized collections that are wrappers around the CPS evaluation cache's collection. The ProjectPropertyInstance, ProjectItemInstance, etc. objects were created ahead of time and associated with the corresponding CPS object, such that only one copy of the collections needed to exist. In this PR, the goal is to extend that further such that the ProjectPropertyInstance, ProjectItemInstance, etc. values are only created when they're actually needed, and some new logic is introduced for reading Property values and Metadata values that allows avoiding creating the ProjectPropertyInstance and ProjectMetadataInstance when all that's sought is the EscapedValue string. ### Changes Made The collections for ProjectInstance's _properties, _itemDefinitions, _items, _itemsByEvaluatedInclude, _globalProperties, _targets, _importPaths, and _importPathsincludingDuplicates collections are replaced with specialized virtualizing collections that wrap the associated CPS collection. These collections create the ProjectPropertyInstance et al objects only when a caller requests them. Additionally, the ProjectItemDefinitionInstance's metadata collection, and the ProjectItemInstance's ItemDefinition and Metadata collections are all similarly replaced by a virtualizing collection. ProjectInstance's _environmentVariableProperties still relies on the ProjectCollection's EnvironmentVariables, but a new SharedReadOnlyEnvironmentProperties collection is introduced that does not hand out copies of the PropertyDictionary, but instead the same PropertyDictionary instance whose backing collection has been made read only. ### Testing Manual verification of impacted scenarios and performance measurements.
- Loading branch information
1 parent
147ecad
commit eade720
Showing
29 changed files
with
1,582 additions
and
297 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using Microsoft.Build.Shared; | ||
|
||
#nullable disable | ||
|
||
namespace Microsoft.Build.Collections | ||
{ | ||
/// <summary> | ||
/// An interface that represents a dictionary of unordered property or metadata name/value pairs with copy-on-write semantics. | ||
/// </summary> | ||
/// <remarks> | ||
/// The value that this adds over IDictionary<string, T> is: | ||
/// - supports copy on write | ||
/// - enforces that key = T.Name | ||
/// - default enumerator is over values | ||
/// - (marginal) enforces the correct key comparer | ||
/// | ||
/// Really a Dictionary<string, T> where the key (the name) is obtained from IKeyed.Key. | ||
/// Is not observable, so if clients wish to observe modifications they must mediate them themselves and | ||
/// either not expose this collection or expose it through a readonly wrapper. | ||
/// | ||
/// This collection is safe for concurrent readers and a single writer. | ||
/// </remarks> | ||
/// <typeparam name="T">Property or Metadata class type to store</typeparam> | ||
internal interface ICopyOnWritePropertyDictionary<T> : IEnumerable<T>, IEquatable<ICopyOnWritePropertyDictionary<T>>, IDictionary<string, T> | ||
where T : class, IKeyed, IValued, IEquatable<T>, IImmutable | ||
{ | ||
/// <summary> | ||
/// Returns true if a property with the specified name is present in the collection, otherwise false. | ||
/// </summary> | ||
bool Contains(string name); | ||
|
||
/// <summary> | ||
/// Add the specified property to the collection. | ||
/// Overwrites any property with the same name already in the collection. | ||
/// To remove a property, use Remove(...) instead. | ||
/// </summary> | ||
void Set(T projectProperty); | ||
|
||
/// <summary> | ||
/// Adds the specified properties to this dictionary. | ||
/// </summary> | ||
/// <param name="other">An enumerator over the properties to add.</param> | ||
void ImportProperties(IEnumerable<T> other); | ||
|
||
/// <summary> | ||
/// Clone. As we're copy on write, this should be cheap. | ||
/// </summary> | ||
ICopyOnWritePropertyDictionary<T> DeepClone(); | ||
|
||
/// <summary> | ||
/// <typeparamref name="T"/> must implement <see cref="IKeyed"/>, which means it contains an | ||
/// EscapedValue. This method allows retrieving the EscapedValue of an object in the dictionary | ||
/// directly. | ||
/// </summary> | ||
string GetEscapedValue(string name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Microsoft.Build.Collections | ||
{ | ||
/// <summary> | ||
/// Represents a dictionary that can hold more than one distinct value with the same key. | ||
/// All keys must have at least one value: null values are currently rejected. | ||
/// </summary> | ||
/// <typeparam name="K">Type of key</typeparam> | ||
/// <typeparam name="V">Type of value</typeparam> | ||
internal interface IMultiDictionary<K, V> | ||
where K : class | ||
where V : class | ||
{ | ||
IEnumerable<V> this[K key] { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.