Memory usage improvements in build (#2626)
* Use a WorkspaceContext in dotnet-build to cache project data across multiple compilations in a single build action * Dramatically reduce string and object duplication by introducing a "Symbol Table" that shares instances of NuGetVersion, NuGetFramework, VersionRange and string across multiple lock-file parses Test Results: * Testing was done by compiling Microsoft.AspNetCore.Mvc (and it's dependencies) and taking memory snapshots after each compilation in dotMemory * We used to allocate ~3MB and deallocate ~2.5MB on EACH compilation in a single build action. This has been reduced to ~120KB allocated/deallocated * After introducing WorkspaceContext, total memory usage spiked from 6MB across the whole build action to about 13MB, introducing the symbol table dropped it back to about 5-6MB.
This commit is contained in:
parent
80df3688b1
commit
ef0ca39da1
42 changed files with 496 additions and 268 deletions
|
@ -22,6 +22,7 @@ namespace Microsoft.DotNet.Tools.Run
|
|||
|
||||
ProjectContext _context;
|
||||
List<string> _args;
|
||||
private WorkspaceContext _workspace;
|
||||
|
||||
public int Start()
|
||||
{
|
||||
|
@ -60,6 +61,8 @@ namespace Microsoft.DotNet.Tools.Run
|
|||
Configuration = Constants.DefaultConfiguration;
|
||||
}
|
||||
|
||||
var frameworkContexts = _workspace.GetProjectContexts(Project).Where(c => string.IsNullOrEmpty(c.RuntimeIdentifier));
|
||||
|
||||
var rids = PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
|
||||
|
||||
if (Framework == null)
|
||||
|
@ -70,16 +73,14 @@ namespace Microsoft.DotNet.Tools.Run
|
|||
FrameworkConstants.FrameworkIdentifiers.NetStandardApp,
|
||||
};
|
||||
|
||||
var contexts = ProjectContext.CreateContextForEachFramework(Project, null);
|
||||
|
||||
ProjectContext context;
|
||||
if (contexts.Count() == 1)
|
||||
if (frameworkContexts.Count() == 1)
|
||||
{
|
||||
context = contexts.Single();
|
||||
context = frameworkContexts.Single();
|
||||
}
|
||||
else
|
||||
{
|
||||
context = contexts.FirstOrDefault(c => defaultFrameworks.Contains(c.TargetFramework.Framework));
|
||||
context = frameworkContexts.FirstOrDefault(c => defaultFrameworks.Contains(c.TargetFramework.Framework));
|
||||
if (context == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Couldn't find target to run. Possible causes:" + Environment.NewLine +
|
||||
|
@ -88,11 +89,11 @@ namespace Microsoft.DotNet.Tools.Run
|
|||
}
|
||||
}
|
||||
|
||||
_context = context.CreateRuntimeContext(rids);
|
||||
_context = _workspace.GetRuntimeContext(context, rids);
|
||||
}
|
||||
else
|
||||
{
|
||||
_context = ProjectContext.Create(Project, NuGetFramework.Parse(Framework), rids);
|
||||
_context = _workspace.GetProjectContext(Project, NuGetFramework.Parse(Framework), rids);
|
||||
}
|
||||
|
||||
if (Args == null)
|
||||
|
@ -107,6 +108,9 @@ namespace Microsoft.DotNet.Tools.Run
|
|||
|
||||
private int RunExecutable()
|
||||
{
|
||||
// Set up the workspace
|
||||
_workspace = WorkspaceContext.Create(ProjectReaderSettings.ReadFromEnvironment(), designTime: false);
|
||||
|
||||
CalculateDefaultsForNonAssigned();
|
||||
|
||||
// Compile to that directory
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue