Skip to content

Commit abcb361

Browse files
authored
Cache the compilation states in compilation order to avoid recalculation (#76380)
Cache the compilation states in compilation order to avoid recalculation GetStatesInCompilationOrder shows up pretty heavily in CPU usage in the typing scenario in the csharp editing speedometer. The enumerating of the ImmutableList and the repeated searching in the ImmutableSortedDictionary are actually more expensive than one would think. GetStatesInCompilationOrder is optimized out of the profile, but it looks like it is accounting for about 5% of CPU. I'm going to run a test insertion with this change and see what the CPU/memory delta of this method looks like with this change.
1 parent 80b91e9 commit abcb361

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,22 @@ public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IRead
397397
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
398398
}
399399

400+
public static ImmutableArray<TResult> SelectAsArray<TSource, TResult, TArg>(this IReadOnlyCollection<TSource>? source, Func<TSource, TArg, TResult> selector, TArg arg)
401+
{
402+
if (source == null)
403+
return ImmutableArray<TResult>.Empty;
404+
405+
var builder = new TResult[source.Count];
406+
var index = 0;
407+
foreach (var item in source)
408+
{
409+
builder[index] = selector(item, arg);
410+
index++;
411+
}
412+
413+
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
414+
}
415+
400416
public static ImmutableArray<TResult> SelectManyAsArray<TSource, TResult>(this IEnumerable<TSource>? source, Func<TSource, IEnumerable<TResult>> selector)
401417
{
402418
if (source == null)

src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentStates.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ internal sealed class TextDocumentStates<TState>
4949
#endif
5050

5151
private readonly ImmutableList<DocumentId> _ids;
52+
private ImmutableArray<TState> _statesInCompilationOrder;
5253
private FilePathToDocumentIds? _filePathToDocumentIds;
5354

5455
private TextDocumentStates(
@@ -117,10 +118,12 @@ public TState GetRequiredState(DocumentId documentId)
117118
/// Get states ordered in compilation order.
118119
/// </summary>
119120
/// <returns></returns>
120-
public IEnumerable<TState> GetStatesInCompilationOrder()
121+
public ImmutableArray<TState> GetStatesInCompilationOrder()
121122
{
122-
var map = States;
123-
return Ids.Select(id => map[id]);
123+
if (_statesInCompilationOrder.IsDefault)
124+
_statesInCompilationOrder = Ids.SelectAsArray(static (id, map) => map[id], States);
125+
126+
return _statesInCompilationOrder;
124127
}
125128

126129
public ImmutableArray<TValue> SelectAsArray<TValue>(Func<TState, TValue> selector)

0 commit comments

Comments
 (0)