Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #2264 from dotnet/pakrym/dc-memory
Browse files Browse the repository at this point in the history
Optimize dependency context memory usage
  • Loading branch information
pakrym committed May 16, 2016
2 parents c3aa0a5 + 43c638e commit 07b785c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -28,6 +30,19 @@ public DependencyContext Read(Stream stream)
}
}

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)
Expand Down Expand Up @@ -178,8 +193,8 @@ private Library ReadLibrary(JProperty property, bool runtime, Dictionary<string,

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;

Expand Down Expand Up @@ -263,13 +278,13 @@ private IEnumerable<ResourceAssembly> ReadResourceAssemblies(JObject resourcesOb
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)
{
Expand All @@ -281,8 +296,8 @@ private static IEnumerable<RuntimeTargetEntryStub> ReadRuntimeTargetEntries(JObj
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>())
};
}
}
Expand All @@ -299,7 +314,7 @@ private static string[] ReadAssetList(JObject libraryObject, string name)
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];

Expand All @@ -309,7 +324,7 @@ private static Dependency[] ReadDependencies(JObject libraryObject)
}

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)
Expand All @@ -322,9 +337,9 @@ private Dictionary<string, LibraryStub> ReadLibraryStubs(JObject librariesObject
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);
Expand All @@ -333,6 +348,22 @@ private Dictionary<string, LibraryStub> ReadLibraryStubs(JObject librariesObject
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;
Expand Down
50 changes: 26 additions & 24 deletions src/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@ public class DependencyContextLoader
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())
{
}

internal DependencyContextLoader(
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();
Expand All @@ -58,61 +58,63 @@ public DependencyContext Load(Assembly assembly)
}

DependencyContext context = null;

if (IsEntryAssembly(assembly))
using (var reader = _jsonReaderFactory())
{
context = LoadEntryAssemblyContext();
}
if (IsEntryAssembly(assembly))
{
context = LoadEntryAssemblyContext(reader);
}

if (context == null)
{
context = LoadAssemblyContext(assembly);
}
if (context == null)
{
context = LoadAssemblyContext(assembly, reader);
}

if (context?.Target.IsPortable == true)
{
var runtimeContext = LoadRuntimeContext();
if (runtimeContext != null)
if (context?.Target.IsPortable == true)
{
context = context.Merge(runtimeContext);
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);
}
}

Expand All @@ -121,7 +123,7 @@ private DependencyContext LoadAssemblyContext(Assembly assembly)
{
using (var stream = _fileSystem.File.OpenRead(depsJsonFile))
{
return _jsonReader.Read(stream);
return reader.Read(stream);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System;
using System.IO;

namespace Microsoft.Extensions.DependencyModel
{
public interface IDependencyContextReader
public interface IDependencyContextReader: IDisposable
{
DependencyContext Read(Stream stream);
}
Expand Down

0 comments on commit 07b785c

Please sign in to comment.