Skip to content

Commit

Permalink
fix: memory leak
Browse files Browse the repository at this point in the history
  • Loading branch information
workgroupengineering committed Apr 16, 2024
1 parent 7c5e7d1 commit d80a464
Show file tree
Hide file tree
Showing 7 changed files with 322 additions and 168 deletions.
30 changes: 14 additions & 16 deletions AvaloniaVS.Shared/Views/AvaloniaDesigner.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Serilog;
using Task = System.Threading.Tasks.Task;


namespace AvaloniaVS.Views
{
public enum AvaloniaDesignerView
Expand Down Expand Up @@ -443,7 +444,7 @@ public bool TryProcessZoomLevelValue(out double scaling)
Dispatcher.BeginInvoke(() =>
ZoomLevel = string.Format(CultureInfo.InvariantCulture, "{0}%", Math.Round(Math.Min(x, y), 2, MidpointRounding.ToEven) * 100),
System.Windows.Threading.DispatcherPriority.Background);

}
else
{
Expand Down Expand Up @@ -559,7 +560,8 @@ private void RebuildMetadata(string assemblyPath)
string intermediateOutputPath = GetIntermediateOutputPath(storage);
if (metadata.CompletionMetadata == null || metadata.NeedInvalidation)
{
CreateCompletionMetadataAsync(intermediateOutputPath, assemblyPath, metadata).FireAndForget();
CreateCompletionMetadataAsync(intermediateOutputPath, assemblyPath, metadata)
.FireAndForget();
}
}
}
Expand All @@ -572,48 +574,44 @@ private void RebuildMetadata(string assemblyPath)
string xamlAssemblyPath,
XamlBufferMetadata target)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
var sw = new Stopwatch();
sw.Start();
Log.Logger.Information("Started AvaloniaDesigner.CreateCompletionMetadataAsync() for {ExecutablePath}", intermediateOutputPath);

if (_metadataCache == null)
{
_metadataCache = new Dictionary<string, Task<Metadata>>();
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
var dte = (DTE)Package.GetGlobalService(typeof(DTE));

dte.Events.BuildEvents.OnBuildBegin += (s, e) => _metadataCache.Clear();
}

Log.Logger.Information("Started AvaloniaDesigner.CreateCompletionMetadataAsync() for {ExecutablePath}", intermediateOutputPath);

try
{
var sw = Stopwatch.StartNew();
await TaskScheduler.Default;

Task<Metadata> metadataLoad;

if (!_metadataCache.TryGetValue(intermediateOutputPath, out metadataLoad))
{
metadataLoad = Task.Run(() =>
{
return _metadataReader.GetForTargetAssembly(new AvaloniaCompilationAssemblyProvider(intermediateOutputPath, xamlAssemblyPath));
});
metadataLoad?.Dispose();
metadataLoad = Task.Run(() => _metadataReader.GetForTargetAssembly(new AvaloniaCompilationAssemblyProvider(intermediateOutputPath, xamlAssemblyPath)));
_metadataCache[intermediateOutputPath] = metadataLoad;
}
target.CompletionMetadata?.Dispose();

target.CompletionMetadata = await metadataLoad;

target.NeedInvalidation = false;

sw.Stop();

Log.Logger.Verbose("Finished AvaloniaDesigner.CreateCompletionMetadataAsync() took {Time} for {ExecutablePath}", sw.Elapsed, intermediateOutputPath);
}
catch (Exception ex)
{
Log.Logger.Error(ex, "Error creating XAML completion metadata");
}
finally
{
Log.Logger.Verbose("Finished AvaloniaDesigner.CreateCompletionMetadataAsync()");
sw?.Stop();
Log.Logger.Verbose("Finished AvaloniaDesigner.CreateCompletionMetadataAsync() {0}", sw?.Elapsed);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<AssemblyOriginatorKeyFile>$(SolutionDir)Key.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="dnlib" Version="4.1.0" />
<PackageReference Include="dnlib" Version="4.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Ide.CompletionEngine\Avalonia.Ide.CompletionEngine.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -18,10 +19,14 @@ public IMetadataReaderSession GetMetadata(IEnumerable<string> paths)
internal class DnlibMetadataProviderSession : IMetadataReaderSession
{
private readonly ModuleContext _modCtx;
private readonly Dictionary<ITypeDefOrRef, ITypeDefOrRef> _baseTypes = new Dictionary<ITypeDefOrRef, ITypeDefOrRef>();
private readonly Dictionary<ITypeDefOrRef, TypeDef> _baseTypeDefs = new Dictionary<ITypeDefOrRef, TypeDef>();
private readonly Dictionary<ITypeDefOrRef, ITypeDefOrRef> _baseTypes = new();
private readonly Dictionary<ITypeDefOrRef, TypeDef> _baseTypeDefs = new();
private readonly List<IAssemblyInformation> _assemblies = new(200);
internal readonly ConcurrentDictionary<MethodDef, MethodWrapper> _methodsCache = new();
internal readonly ConcurrentDictionary<EventDef, EventWrapper> _eventsCache = new();
internal readonly ConcurrentDictionary<PropertyDef, PropertyWrapper> _propertiesCache = new();
public string? TargetAssemblyName { get; private set; }
public IReadOnlyCollection<IAssemblyInformation> Assemblies { get; }
public IReadOnlyCollection<IAssemblyInformation> Assemblies => _assemblies;
public DnlibMetadataProviderSession(string[] directoryPath)
{
var asmResolver = new AssemblyResolver()
Expand All @@ -39,12 +44,11 @@ public DnlibMetadataProviderSession(string[] directoryPath)
if (directoryPath == null || directoryPath.Length == 0)
{
TargetAssemblyName = null;
Assemblies = Array.Empty<IAssemblyInformation>();
}
else
{
TargetAssemblyName = System.Reflection.AssemblyName.GetAssemblyName(directoryPath[0]).ToString();
Assemblies = LoadAssemblies(_modCtx, directoryPath).Select(a => new AssemblyWrapper(a, this)).ToList();
_assemblies.AddRange(LoadAssemblies(_modCtx, directoryPath).Select(a => new AssemblyWrapper(a, this)));
}
}

Expand Down Expand Up @@ -80,7 +84,6 @@ public ITypeDefOrRef GetBaseType(ITypeDefOrRef type)
{
return _baseTypes[type] = type.GetBaseType();
}

}

private static List<AssemblyDef> LoadAssemblies(ModuleContext context, string[] lst)
Expand All @@ -104,9 +107,10 @@ private static List<AssemblyDef> LoadAssemblies(ModuleContext context, string[]
asmResovler.AddToCache(def);
assemblies.Add(def);
}
catch
catch (Exception ex)
{
//Ignore
System.Diagnostics.Debug.WriteLine(ex);
}
}

Expand All @@ -117,6 +121,12 @@ public void Dispose()
{
_baseTypes.Clear();
_baseTypeDefs.Clear();
_methodsCache.Clear();
_eventsCache.Clear();
_propertiesCache.Clear();
_assemblies.Clear();
((AssemblyResolver)_modCtx.AssemblyResolver).Clear();
_modCtx.AssemblyResolver = null;
_modCtx.Resolver = null;
}
}

0 comments on commit d80a464

Please sign in to comment.