From 41ef4f4c570063a3ffcdb6f6925a475b7c8d16bb Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 6 Jun 2025 15:01:56 -0700 Subject: [PATCH 1/2] Switch off of mutlidictionary This is from ICSharpCompiler, and is therefore causing unnecessary dll loads. --- .../RootSymbolTreeItemSourceProvider.cs | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs index fba000ae74d05..5a95aa788bc75 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs @@ -3,11 +3,11 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Composition; using System.Threading; using System.Threading.Tasks; -using ICSharpCode.Decompiler.Util; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; @@ -44,7 +44,7 @@ internal sealed partial class RootSymbolTreeItemSourceProvider : AttachedCollect /// of that file through that project. /// /// Lock this instance when reading/writing as it is used over different threads. - private readonly MultiDictionary _filePathToCollectionSources = new( + private readonly Dictionary> _filePathToCollectionSources = new( StringComparer.OrdinalIgnoreCase); /// @@ -166,7 +166,9 @@ await source.UpdateIfEverExpandedAsync(cancellationToken) var source = new RootSymbolTreeItemCollectionSource(this, item); lock (_filePathToCollectionSources) - _filePathToCollectionSources.Add(currentFilePath, source); + { + AddToDictionary(currentFilePath, source); + } // Register to hear about if this hierarchy is disposed. We'll stop watching it if so. item.PropertyChanged += OnItemPropertyChanged; @@ -181,7 +183,7 @@ void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e) // event for the IsDisposed property. When this fires, we remove the filePath->sourcce mapping we're holding. lock (_filePathToCollectionSources) { - _filePathToCollectionSources.Remove(currentFilePath, source); + RemoveFromDictionary(currentFilePath, source); } item.PropertyChanged -= OnItemPropertyChanged; @@ -195,8 +197,8 @@ void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e) { // Unlink the oldPath->source mapping, and add a new line for the newPath->source. - _filePathToCollectionSources.Remove(currentFilePath, source); - _filePathToCollectionSources.Add(newPath, source); + RemoveFromDictionary(currentFilePath, source); + AddToDictionary(newPath, source); // Keep track of the 'newPath'. currentFilePath = newPath; @@ -211,5 +213,24 @@ void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e) } } } + + void AddToDictionary(string currentFilePath, RootSymbolTreeItemCollectionSource source) + { + if (!_filePathToCollectionSources.TryGetValue(currentFilePath, out var sources)) + { + sources = []; + _filePathToCollectionSources[currentFilePath] = sources; + } + + sources.Add(source); + } + + void RemoveFromDictionary(string currentFilePath, RootSymbolTreeItemCollectionSource source) + { + if (_filePathToCollectionSources.TryGetValue(currentFilePath, out var sources)) + { + sources.Remove(source); + } + } } } From 2433309d2217726a2faba2f5b1f9a040ec798845 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 6 Jun 2025 15:44:11 -0700 Subject: [PATCH 2/2] Remove paths entirely when there are no more sources --- .../SymbolTree/RootSymbolTreeItemSourceProvider.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs index 5a95aa788bc75..2e4bb424200fc 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs @@ -230,6 +230,11 @@ void RemoveFromDictionary(string currentFilePath, RootSymbolTreeItemCollectionSo if (_filePathToCollectionSources.TryGetValue(currentFilePath, out var sources)) { sources.Remove(source); + + if (sources.Count == 0) + { + _filePathToCollectionSources.Remove(currentFilePath); + } } } }