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:
Andrew Stanton-Nurse 2016-04-22 15:01:56 -07:00
parent 80df3688b1
commit ef0ca39da1
42 changed files with 496 additions and 268 deletions

View file

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
@ -26,7 +27,7 @@ namespace Microsoft.DotNet.ProjectModel.Server
_hostName = hostName;
_loggerFactory = loggerFactory;
_protocolManager = new ProtocolManager(maxVersion: 4, loggerFactory: _loggerFactory);
_workspaceContext = WorkspaceContext.Create();
_workspaceContext = WorkspaceContext.Create(designTime: true);
_projects = new Dictionary<int, ProjectManager>();
}
@ -51,26 +52,34 @@ namespace Microsoft.DotNet.ProjectModel.Server
var logger = loggerFactory.CreateLogger<ProjectModelServerCommand>();
if (!MonitorHostProcess(hostpid, logger))
try
{
return 1;
}
if (!MonitorHostProcess(hostpid, logger))
{
return 1;
}
var intPort = CheckPort(port, logger);
if (intPort == -1)
var intPort = CheckPort(port, logger);
if (intPort == -1)
{
return 1;
}
if (!hostname.HasValue())
{
logger.LogError($"Option \"{hostname.LongName}\" is missing.");
return 1;
}
var program = new ProjectModelServerCommand(intPort, hostname.Value(), loggerFactory);
program.OpenChannel();
}
catch (Exception ex)
{
return 1;
logger.LogCritical($"Unhandled exception in server main: {ex}");
throw;
}
if (!hostname.HasValue())
{
logger.LogError($"Option \"{hostname.LongName}\" is missing.");
return 1;
}
var program = new ProjectModelServerCommand(intPort, hostname.Value(), loggerFactory);
program.OpenChannel();
return 0;
});