Merge pull request #2264 from dotnet/pakrym/dc-memory
Optimize dependency context memory usage
This commit is contained in:
commit
07b785c183
3 changed files with 71 additions and 37 deletions
|
@ -12,6 +12,8 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
public class DependencyContextJsonReader : IDependencyContextReader
|
public class DependencyContextJsonReader : IDependencyContextReader
|
||||||
{
|
{
|
||||||
|
private readonly IDictionary<string, string> _stringPool = new Dictionary<string, string>();
|
||||||
|
|
||||||
public DependencyContext Read(Stream stream)
|
public DependencyContext Read(Stream stream)
|
||||||
{
|
{
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
|
@ -28,6 +30,19 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_stringPool.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsRuntimeTarget(string name) => name.Contains(DependencyContextStrings.VersionSeperator);
|
private bool IsRuntimeTarget(string name) => name.Contains(DependencyContextStrings.VersionSeperator);
|
||||||
|
|
||||||
private DependencyContext Read(JObject root)
|
private DependencyContext Read(JObject root)
|
||||||
|
@ -178,8 +193,8 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
|
|
||||||
var seperatorPosition = nameWithVersion.IndexOf(DependencyContextStrings.VersionSeperator);
|
var seperatorPosition = nameWithVersion.IndexOf(DependencyContextStrings.VersionSeperator);
|
||||||
|
|
||||||
var name = nameWithVersion.Substring(0, seperatorPosition);
|
var name = Pool(nameWithVersion.Substring(0, seperatorPosition));
|
||||||
var version = nameWithVersion.Substring(seperatorPosition + 1);
|
var version = Pool(nameWithVersion.Substring(seperatorPosition + 1));
|
||||||
|
|
||||||
var libraryObject = (JObject)property.Value;
|
var libraryObject = (JObject)property.Value;
|
||||||
|
|
||||||
|
@ -263,13 +278,13 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
foreach (var resourceProperty in resourcesObject)
|
foreach (var resourceProperty in resourcesObject)
|
||||||
{
|
{
|
||||||
yield return new ResourceAssembly(
|
yield return new ResourceAssembly(
|
||||||
locale: resourceProperty.Value[DependencyContextStrings.LocalePropertyName]?.Value<string>(),
|
locale: Pool(resourceProperty.Value[DependencyContextStrings.LocalePropertyName]?.Value<string>()),
|
||||||
path: resourceProperty.Key
|
path: resourceProperty.Key
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<RuntimeTargetEntryStub> ReadRuntimeTargetEntries(JObject runtimeTargetObject)
|
private IEnumerable<RuntimeTargetEntryStub> ReadRuntimeTargetEntries(JObject runtimeTargetObject)
|
||||||
{
|
{
|
||||||
if (runtimeTargetObject == null)
|
if (runtimeTargetObject == null)
|
||||||
{
|
{
|
||||||
|
@ -281,8 +296,8 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
yield return new RuntimeTargetEntryStub()
|
yield return new RuntimeTargetEntryStub()
|
||||||
{
|
{
|
||||||
Path = libraryProperty.Key,
|
Path = libraryProperty.Key,
|
||||||
Rid = libraryObject[DependencyContextStrings.RidPropertyName].Value<string>(),
|
Rid = Pool(libraryObject[DependencyContextStrings.RidPropertyName].Value<string>()),
|
||||||
Type = libraryObject[DependencyContextStrings.AssetTypePropertyName].Value<string>()
|
Type = Pool(libraryObject[DependencyContextStrings.AssetTypePropertyName].Value<string>())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,7 +314,7 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
return assembliesObject.Properties().Select(property => property.Name).ToArray();
|
return assembliesObject.Properties().Select(property => property.Name).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dependency[] ReadDependencies(JObject libraryObject)
|
private Dependency[] ReadDependencies(JObject libraryObject)
|
||||||
{
|
{
|
||||||
var dependenciesObject = (JObject)libraryObject[DependencyContextStrings.DependenciesPropertyName];
|
var dependenciesObject = (JObject)libraryObject[DependencyContextStrings.DependenciesPropertyName];
|
||||||
|
|
||||||
|
@ -309,7 +324,7 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
}
|
}
|
||||||
|
|
||||||
return dependenciesObject.Properties()
|
return dependenciesObject.Properties()
|
||||||
.Select(property => new Dependency(property.Name, (string)property.Value)).ToArray();
|
.Select(property => new Dependency(Pool(property.Name), Pool((string)property.Value))).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, LibraryStub> ReadLibraryStubs(JObject librariesObject)
|
private Dictionary<string, LibraryStub> ReadLibraryStubs(JObject librariesObject)
|
||||||
|
@ -322,9 +337,9 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
var value = (JObject)libraryProperty.Value;
|
var value = (JObject)libraryProperty.Value;
|
||||||
var stub = new LibraryStub
|
var stub = new LibraryStub
|
||||||
{
|
{
|
||||||
Name = libraryProperty.Key,
|
Name = Pool(libraryProperty.Key),
|
||||||
Hash = value[DependencyContextStrings.Sha512PropertyName]?.Value<string>(),
|
Hash = value[DependencyContextStrings.Sha512PropertyName]?.Value<string>(),
|
||||||
Type = value[DependencyContextStrings.TypePropertyName].Value<string>(),
|
Type = Pool(value[DependencyContextStrings.TypePropertyName].Value<string>()),
|
||||||
Serviceable = value[DependencyContextStrings.ServiceablePropertyName]?.Value<bool>() == true
|
Serviceable = value[DependencyContextStrings.ServiceablePropertyName]?.Value<bool>() == true
|
||||||
};
|
};
|
||||||
libraries.Add(stub.Name, stub);
|
libraries.Add(stub.Name, stub);
|
||||||
|
@ -333,6 +348,22 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
return libraries;
|
return libraries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string Pool(string s)
|
||||||
|
{
|
||||||
|
if (s == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string result;
|
||||||
|
if (!_stringPool.TryGetValue(s, out result))
|
||||||
|
{
|
||||||
|
_stringPool[s] = s;
|
||||||
|
result = s;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private struct RuntimeTargetEntryStub
|
private struct RuntimeTargetEntryStub
|
||||||
{
|
{
|
||||||
public string Type;
|
public string Type;
|
||||||
|
|
|
@ -16,13 +16,13 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
private readonly string _entryPointDepsLocation;
|
private readonly string _entryPointDepsLocation;
|
||||||
private readonly string _runtimeDepsLocation;
|
private readonly string _runtimeDepsLocation;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IDependencyContextReader _jsonReader;
|
private readonly Func<IDependencyContextReader> _jsonReaderFactory;
|
||||||
|
|
||||||
public DependencyContextLoader() : this(
|
public DependencyContextLoader() : this(
|
||||||
DependencyContextPaths.Current.Application,
|
DependencyContextPaths.Current.Application,
|
||||||
DependencyContextPaths.Current.SharedRuntime,
|
DependencyContextPaths.Current.SharedRuntime,
|
||||||
FileSystemWrapper.Default,
|
FileSystemWrapper.Default,
|
||||||
new DependencyContextJsonReader())
|
() => new DependencyContextJsonReader())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
string entryPointDepsLocation,
|
string entryPointDepsLocation,
|
||||||
string runtimeDepsLocation,
|
string runtimeDepsLocation,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IDependencyContextReader jsonReader)
|
Func<IDependencyContextReader> jsonReaderFactory)
|
||||||
{
|
{
|
||||||
_entryPointDepsLocation = entryPointDepsLocation;
|
_entryPointDepsLocation = entryPointDepsLocation;
|
||||||
_runtimeDepsLocation = runtimeDepsLocation;
|
_runtimeDepsLocation = runtimeDepsLocation;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_jsonReader = jsonReader;
|
_jsonReaderFactory = jsonReaderFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DependencyContextLoader Default { get; } = new DependencyContextLoader();
|
public static DependencyContextLoader Default { get; } = new DependencyContextLoader();
|
||||||
|
@ -58,61 +58,63 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
}
|
}
|
||||||
|
|
||||||
DependencyContext context = null;
|
DependencyContext context = null;
|
||||||
|
using (var reader = _jsonReaderFactory())
|
||||||
if (IsEntryAssembly(assembly))
|
|
||||||
{
|
{
|
||||||
context = LoadEntryAssemblyContext();
|
if (IsEntryAssembly(assembly))
|
||||||
}
|
|
||||||
|
|
||||||
if (context == null)
|
|
||||||
{
|
|
||||||
context = LoadAssemblyContext(assembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context?.Target.IsPortable == true)
|
|
||||||
{
|
|
||||||
var runtimeContext = LoadRuntimeContext();
|
|
||||||
if (runtimeContext != null)
|
|
||||||
{
|
{
|
||||||
context = context.Merge(runtimeContext);
|
context = LoadEntryAssemblyContext(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
context = LoadAssemblyContext(assembly, reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context?.Target.IsPortable == true)
|
||||||
|
{
|
||||||
|
var runtimeContext = LoadRuntimeContext(reader);
|
||||||
|
if (runtimeContext != null)
|
||||||
|
{
|
||||||
|
context = context.Merge(runtimeContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DependencyContext LoadEntryAssemblyContext()
|
private DependencyContext LoadEntryAssemblyContext(IDependencyContextReader reader)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_entryPointDepsLocation))
|
if (!string.IsNullOrEmpty(_entryPointDepsLocation))
|
||||||
{
|
{
|
||||||
Debug.Assert(File.Exists(_entryPointDepsLocation));
|
Debug.Assert(File.Exists(_entryPointDepsLocation));
|
||||||
using (var stream = _fileSystem.File.OpenRead(_entryPointDepsLocation))
|
using (var stream = _fileSystem.File.OpenRead(_entryPointDepsLocation))
|
||||||
{
|
{
|
||||||
return _jsonReader.Read(stream);
|
return reader.Read(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DependencyContext LoadRuntimeContext()
|
private DependencyContext LoadRuntimeContext(IDependencyContextReader reader)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_runtimeDepsLocation))
|
if (!string.IsNullOrEmpty(_runtimeDepsLocation))
|
||||||
{
|
{
|
||||||
Debug.Assert(File.Exists(_runtimeDepsLocation));
|
Debug.Assert(File.Exists(_runtimeDepsLocation));
|
||||||
using (var stream = _fileSystem.File.OpenRead(_runtimeDepsLocation))
|
using (var stream = _fileSystem.File.OpenRead(_runtimeDepsLocation))
|
||||||
{
|
{
|
||||||
return _jsonReader.Read(stream);
|
return reader.Read(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DependencyContext LoadAssemblyContext(Assembly assembly)
|
private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyContextReader reader)
|
||||||
{
|
{
|
||||||
using (var stream = GetResourceStream(assembly, assembly.GetName().Name + DepsJsonExtension))
|
using (var stream = GetResourceStream(assembly, assembly.GetName().Name + DepsJsonExtension))
|
||||||
{
|
{
|
||||||
if (stream != null)
|
if (stream != null)
|
||||||
{
|
{
|
||||||
return _jsonReader.Read(stream);
|
return reader.Read(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +123,7 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
using (var stream = _fileSystem.File.OpenRead(depsJsonFile))
|
using (var stream = _fileSystem.File.OpenRead(depsJsonFile))
|
||||||
{
|
{
|
||||||
return _jsonReader.Read(stream);
|
return reader.Read(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyModel
|
namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
public interface IDependencyContextReader
|
public interface IDependencyContextReader: IDisposable
|
||||||
{
|
{
|
||||||
DependencyContext Read(Stream stream);
|
DependencyContext Read(Stream stream);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue