Skip to content

Commit

Permalink
Delete ImmutableHashMap
Browse files Browse the repository at this point in the history
This doesn't seem to be notably faster than just using the framework
library; in a case where we're doing an excessive number of GetProject
calls this only is saving us a few dozen milliseconds over all of
loading Roslyn.sln.
  • Loading branch information
jasonmalinowski committed Oct 1, 2021
1 parent f23b88f commit c6cf7d9
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 1,212 deletions.
54 changes: 37 additions & 17 deletions src/Workspaces/Core/Portable/Workspace/Solution/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Collections.Immutable;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis
Expand All @@ -28,10 +27,10 @@ public partial class Project
{
private readonly Solution _solution;
private readonly ProjectState _projectState;
private ImmutableHashMap<DocumentId, Document> _idToDocumentMap = ImmutableHashMap<DocumentId, Document>.Empty;
private ImmutableHashMap<DocumentId, SourceGeneratedDocument> _idToSourceGeneratedDocumentMap = ImmutableHashMap<DocumentId, SourceGeneratedDocument>.Empty;
private ImmutableHashMap<DocumentId, AdditionalDocument> _idToAdditionalDocumentMap = ImmutableHashMap<DocumentId, AdditionalDocument>.Empty;
private ImmutableHashMap<DocumentId, AnalyzerConfigDocument> _idToAnalyzerConfigDocumentMap = ImmutableHashMap<DocumentId, AnalyzerConfigDocument>.Empty;
private ImmutableDictionary<DocumentId, Document> _idToDocumentMap = ImmutableDictionary<DocumentId, Document>.Empty;
private ImmutableDictionary<DocumentId, SourceGeneratedDocument> _idToSourceGeneratedDocumentMap = ImmutableDictionary<DocumentId, SourceGeneratedDocument>.Empty;
private ImmutableDictionary<DocumentId, AdditionalDocument> _idToAdditionalDocumentMap = ImmutableDictionary<DocumentId, AdditionalDocument>.Empty;
private ImmutableDictionary<DocumentId, AnalyzerConfigDocument> _idToAnalyzerConfigDocumentMap = ImmutableDictionary<DocumentId, AnalyzerConfigDocument>.Empty;

internal Project(Solution solution, ProjectState projectState)
{
Expand Down Expand Up @@ -227,19 +226,40 @@ public bool ContainsAnalyzerConfigDocument(DocumentId documentId)
/// Get the document in this project with the specified document Id.
/// </summary>
public Document? GetDocument(DocumentId documentId)
=> ImmutableHashMapExtensions.GetOrAdd(ref _idToDocumentMap, documentId, s_tryCreateDocumentFunction, this);
{
if (ContainsDocument(documentId))
{
return ImmutableInterlocked.GetOrAdd(ref _idToDocumentMap, documentId, s_tryCreateDocumentFunction, this);
}

return null;
}

/// <summary>
/// Get the additional document in this project with the specified document Id.
/// </summary>
public TextDocument? GetAdditionalDocument(DocumentId documentId)
=> ImmutableHashMapExtensions.GetOrAdd(ref _idToAdditionalDocumentMap, documentId, s_tryCreateAdditionalDocumentFunction, this);
{
if (ContainsAdditionalDocument(documentId))
{
return ImmutableInterlocked.GetOrAdd(ref _idToAdditionalDocumentMap, documentId, s_tryCreateAdditionalDocumentFunction, this);
}

return null;
}

/// <summary>
/// Get the analyzer config document in this project with the specified document Id.
/// </summary>
public AnalyzerConfigDocument? GetAnalyzerConfigDocument(DocumentId documentId)
=> ImmutableHashMapExtensions.GetOrAdd(ref _idToAnalyzerConfigDocumentMap, documentId, s_tryCreateAnalyzerConfigDocumentFunction, this);
{
if (ContainsAnalyzerConfigDocument(documentId))
{
return ImmutableInterlocked.GetOrAdd(ref _idToAnalyzerConfigDocumentMap, documentId, s_tryCreateAnalyzerConfigDocumentFunction, this);
}

return null;
}

/// <summary>
/// Gets a document or a source generated document in this solution with the specified document ID.
Expand Down Expand Up @@ -278,7 +298,7 @@ public async ValueTask<IEnumerable<SourceGeneratedDocument>> GetSourceGeneratedD

// return an iterator to avoid eagerly allocating all the document instances
return generatedDocumentStates.States.Values.Select(state =>
ImmutableHashMapExtensions.GetOrAdd(ref _idToSourceGeneratedDocumentMap, state.Id, s_createSourceGeneratedDocumentFunction, (state, this)))!;
ImmutableInterlocked.GetOrAdd(ref _idToSourceGeneratedDocumentMap, state.Id, s_createSourceGeneratedDocumentFunction, (state, this)))!;
}

internal async ValueTask<IEnumerable<Document>> GetAllRegularAndSourceGeneratedDocumentsAsync(CancellationToken cancellationToken = default)
Expand Down Expand Up @@ -306,7 +326,7 @@ internal async ValueTask<IEnumerable<Document>> GetAllRegularAndSourceGeneratedD
}

internal SourceGeneratedDocument GetOrCreateSourceGeneratedDocument(SourceGeneratedDocumentState state)
=> ImmutableHashMapExtensions.GetOrAdd(ref _idToSourceGeneratedDocumentMap, state.Id, s_createSourceGeneratedDocumentFunction, (state, this))!;
=> ImmutableInterlocked.GetOrAdd(ref _idToSourceGeneratedDocumentMap, state.Id, s_createSourceGeneratedDocumentFunction, (state, this))!;

/// <summary>
/// Returns the <see cref="SourceGeneratedDocumentState"/> for a source generated document that has already been generated and observed.
Expand All @@ -333,7 +353,7 @@ internal SourceGeneratedDocument GetOrCreateSourceGeneratedDocument(SourceGenera
return null;
}

return ImmutableHashMapExtensions.GetOrAdd(ref _idToSourceGeneratedDocumentMap, documentId, s_createSourceGeneratedDocumentFunction, (documentState, this));
return ImmutableInterlocked.GetOrAdd(ref _idToSourceGeneratedDocumentMap, documentId, s_createSourceGeneratedDocumentFunction, (documentState, this));
}

internal Task<bool> ContainsSymbolsWithNameAsync(
Expand Down Expand Up @@ -407,14 +427,14 @@ private async Task<bool> ContainsSymbolsAsync(
return results.Any(b => b);
}

private static readonly Func<DocumentId, Project, Document?> s_tryCreateDocumentFunction =
(documentId, project) => project._projectState.DocumentStates.TryGetState(documentId, out var state) ? new Document(project, state) : null;
private static readonly Func<DocumentId, Project, Document> s_tryCreateDocumentFunction =
(documentId, project) => new Document(project, project.State.DocumentStates.GetRequiredState(documentId));

private static readonly Func<DocumentId, Project, AdditionalDocument?> s_tryCreateAdditionalDocumentFunction =
(documentId, project) => project._projectState.AdditionalDocumentStates.TryGetState(documentId, out var state) ? new AdditionalDocument(project, state) : null;
private static readonly Func<DocumentId, Project, AdditionalDocument> s_tryCreateAdditionalDocumentFunction =
(documentId, project) => new AdditionalDocument(project, project.State.AdditionalDocumentStates.GetRequiredState(documentId));

private static readonly Func<DocumentId, Project, AnalyzerConfigDocument?> s_tryCreateAnalyzerConfigDocumentFunction =
(documentId, project) => project._projectState.AnalyzerConfigDocumentStates.TryGetState(documentId, out var state) ? new AnalyzerConfigDocument(project, state) : null;
private static readonly Func<DocumentId, Project, AnalyzerConfigDocument> s_tryCreateAnalyzerConfigDocumentFunction =
(documentId, project) => new AnalyzerConfigDocument(project, project.State.AnalyzerConfigDocumentStates.GetRequiredState(documentId));

private static readonly Func<DocumentId, (SourceGeneratedDocumentState state, Project project), SourceGeneratedDocument> s_createSourceGeneratedDocumentFunction =
(documentId, stateAndProject) => new SourceGeneratedDocument(stateAndProject.project, stateAndProject.state);
Expand Down
6 changes: 2 additions & 4 deletions src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Collections.Immutable;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis
Expand All @@ -29,11 +28,10 @@ public partial class Solution
private readonly SolutionState _state;

// Values for all these are created on demand.
private ImmutableHashMap<ProjectId, Project> _projectIdToProjectMap;
private ImmutableDictionary<ProjectId, Project> _projectIdToProjectMap = ImmutableDictionary<ProjectId, Project>.Empty;

private Solution(SolutionState state)
{
_projectIdToProjectMap = ImmutableHashMap<ProjectId, Project>.Empty;
_state = state;
}

Expand Down Expand Up @@ -101,7 +99,7 @@ internal Solution(Workspace workspace, SolutionInfo.SolutionAttributes solutionA
{
if (this.ContainsProject(projectId))
{
return ImmutableHashMapExtensions.GetOrAdd(ref _projectIdToProjectMap, projectId, s_createProjectFunction, this);
return ImmutableInterlocked.GetOrAdd(ref _projectIdToProjectMap, projectId, s_createProjectFunction, this);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Extensions\TextSpanExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utilities\CompilerUtilities\CompilerPathUtilities.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utilities\CompilerUtilities\ImmutableDictionaryExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utilities\CompilerUtilities\ImmutableHashMap.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utilities\CompilerUtilities\ImmutableHashMapExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utilities\ConcatImmutableArray`1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utilities\ReferenceCountedDisposable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utilities\ReferenceCountedDisposableCache.cs" />
Expand Down
Loading

0 comments on commit c6cf7d9

Please sign in to comment.