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
|
||||
{
|
||||
private readonly IDictionary<string, string> _stringPool = new Dictionary<string, string>();
|
||||
|
||||
public DependencyContext Read(Stream stream)
|
||||
{
|
||||
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 DependencyContext Read(JObject root)
|
||||
|
@ -178,8 +193,8 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
|
||||
var seperatorPosition = nameWithVersion.IndexOf(DependencyContextStrings.VersionSeperator);
|
||||
|
||||
var name = nameWithVersion.Substring(0, seperatorPosition);
|
||||
var version = nameWithVersion.Substring(seperatorPosition + 1);
|
||||
var name = Pool(nameWithVersion.Substring(0, seperatorPosition));
|
||||
var version = Pool(nameWithVersion.Substring(seperatorPosition + 1));
|
||||
|
||||
var libraryObject = (JObject)property.Value;
|
||||
|
||||
|
@ -263,13 +278,13 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
foreach (var resourceProperty in resourcesObject)
|
||||
{
|
||||
yield return new ResourceAssembly(
|
||||
locale: resourceProperty.Value[DependencyContextStrings.LocalePropertyName]?.Value<string>(),
|
||||
locale: Pool(resourceProperty.Value[DependencyContextStrings.LocalePropertyName]?.Value<string>()),
|
||||
path: resourceProperty.Key
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<RuntimeTargetEntryStub> ReadRuntimeTargetEntries(JObject runtimeTargetObject)
|
||||
private IEnumerable<RuntimeTargetEntryStub> ReadRuntimeTargetEntries(JObject runtimeTargetObject)
|
||||
{
|
||||
if (runtimeTargetObject == null)
|
||||
{
|
||||
|
@ -281,8 +296,8 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
yield return new RuntimeTargetEntryStub()
|
||||
{
|
||||
Path = libraryProperty.Key,
|
||||
Rid = libraryObject[DependencyContextStrings.RidPropertyName].Value<string>(),
|
||||
Type = libraryObject[DependencyContextStrings.AssetTypePropertyName].Value<string>()
|
||||
Rid = Pool(libraryObject[DependencyContextStrings.RidPropertyName].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();
|
||||
}
|
||||
|
||||
private static Dependency[] ReadDependencies(JObject libraryObject)
|
||||
private Dependency[] ReadDependencies(JObject libraryObject)
|
||||
{
|
||||
var dependenciesObject = (JObject)libraryObject[DependencyContextStrings.DependenciesPropertyName];
|
||||
|
||||
|
@ -309,7 +324,7 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -322,9 +337,9 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
var value = (JObject)libraryProperty.Value;
|
||||
var stub = new LibraryStub
|
||||
{
|
||||
Name = libraryProperty.Key,
|
||||
Name = Pool(libraryProperty.Key),
|
||||
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
|
||||
};
|
||||
libraries.Add(stub.Name, stub);
|
||||
|
@ -333,6 +348,22 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
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
|
||||
{
|
||||
public string Type;
|
||||
|
|
|
@ -16,13 +16,13 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
private readonly string _entryPointDepsLocation;
|
||||
private readonly string _runtimeDepsLocation;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IDependencyContextReader _jsonReader;
|
||||
private readonly Func<IDependencyContextReader> _jsonReaderFactory;
|
||||
|
||||
public DependencyContextLoader() : this(
|
||||
DependencyContextPaths.Current.Application,
|
||||
DependencyContextPaths.Current.SharedRuntime,
|
||||
FileSystemWrapper.Default,
|
||||
new DependencyContextJsonReader())
|
||||
() => new DependencyContextJsonReader())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -30,12 +30,12 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
string entryPointDepsLocation,
|
||||
string runtimeDepsLocation,
|
||||
IFileSystem fileSystem,
|
||||
IDependencyContextReader jsonReader)
|
||||
Func<IDependencyContextReader> jsonReaderFactory)
|
||||
{
|
||||
_entryPointDepsLocation = entryPointDepsLocation;
|
||||
_runtimeDepsLocation = runtimeDepsLocation;
|
||||
_fileSystem = fileSystem;
|
||||
_jsonReader = jsonReader;
|
||||
_jsonReaderFactory = jsonReaderFactory;
|
||||
}
|
||||
|
||||
public static DependencyContextLoader Default { get; } = new DependencyContextLoader();
|
||||
|
@ -58,61 +58,63 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
}
|
||||
|
||||
DependencyContext context = null;
|
||||
|
||||
if (IsEntryAssembly(assembly))
|
||||
using (var reader = _jsonReaderFactory())
|
||||
{
|
||||
context = LoadEntryAssemblyContext();
|
||||
}
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
context = LoadAssemblyContext(assembly);
|
||||
}
|
||||
|
||||
if (context?.Target.IsPortable == true)
|
||||
{
|
||||
var runtimeContext = LoadRuntimeContext();
|
||||
if (runtimeContext != null)
|
||||
if (IsEntryAssembly(assembly))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
private DependencyContext LoadEntryAssemblyContext()
|
||||
private DependencyContext LoadEntryAssemblyContext(IDependencyContextReader reader)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_entryPointDepsLocation))
|
||||
{
|
||||
Debug.Assert(File.Exists(_entryPointDepsLocation));
|
||||
using (var stream = _fileSystem.File.OpenRead(_entryPointDepsLocation))
|
||||
{
|
||||
return _jsonReader.Read(stream);
|
||||
return reader.Read(stream);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private DependencyContext LoadRuntimeContext()
|
||||
private DependencyContext LoadRuntimeContext(IDependencyContextReader reader)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_runtimeDepsLocation))
|
||||
{
|
||||
Debug.Assert(File.Exists(_runtimeDepsLocation));
|
||||
using (var stream = _fileSystem.File.OpenRead(_runtimeDepsLocation))
|
||||
{
|
||||
return _jsonReader.Read(stream);
|
||||
return reader.Read(stream);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private DependencyContext LoadAssemblyContext(Assembly assembly)
|
||||
private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyContextReader reader)
|
||||
{
|
||||
using (var stream = GetResourceStream(assembly, assembly.GetName().Name + DepsJsonExtension))
|
||||
{
|
||||
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))
|
||||
{
|
||||
return _jsonReader.Read(stream);
|
||||
return reader.Read(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyModel
|
||||
{
|
||||
public interface IDependencyContextReader
|
||||
public interface IDependencyContextReader: IDisposable
|
||||
{
|
||||
DependencyContext Read(Stream stream);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue