Skip to content

Commit 67cf09a

Browse files
committed
Reduce allocations in ModuleSymbolKey.Resolve
Related to https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2136177
1 parent 33e4c03 commit 67cf09a

File tree

2 files changed

+27
-13
lines changed

2 files changed

+27
-13
lines changed

src/Compilers/CSharp/Portable/Symbols/PublicModel/AssemblySymbol.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,18 @@
44

55
#nullable disable
66

7-
using System;
8-
using System.Collections.Concurrent;
97
using System.Collections.Generic;
108
using System.Collections.Immutable;
119
using System.Diagnostics;
12-
using System.Globalization;
1310
using System.Linq;
14-
using System.Threading;
15-
using Microsoft.CodeAnalysis.Collections;
16-
using Microsoft.CodeAnalysis.PooledObjects;
11+
using Roslyn.Utilities;
1712

1813
namespace Microsoft.CodeAnalysis.CSharp.Symbols.PublicModel
1914
{
2015
internal abstract class AssemblySymbol : Symbol, IAssemblySymbol
2116
{
17+
private IEnumerable<IModuleSymbol> _lazyModules;
18+
2219
internal abstract Symbols.AssemblySymbol UnderlyingAssemblySymbol { get; }
2320

2421
INamespaceSymbol IAssemblySymbol.GlobalNamespace
@@ -33,10 +30,10 @@ IEnumerable<IModuleSymbol> IAssemblySymbol.Modules
3330
{
3431
get
3532
{
36-
foreach (var module in UnderlyingAssemblySymbol.Modules)
37-
{
38-
yield return module.GetPublicSymbol();
39-
}
33+
return InterlockedOperations.Initialize(
34+
ref _lazyModules,
35+
static self => self.UnderlyingAssemblySymbol.Modules.SelectAsArray(static module => module.GetPublicSymbol()),
36+
this);
4037
}
4138
}
4239

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/SymbolKey/SymbolKey.ModuleSymbolKey.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Collections.Immutable;
6+
57
namespace Microsoft.CodeAnalysis;
68

79
internal partial struct SymbolKey
@@ -24,12 +26,27 @@ protected sealed override SymbolKeyResolution Resolve(
2426
return default;
2527
}
2628

27-
using var result = PooledArrayBuilder<IModuleSymbol>.GetInstance();
28-
foreach (var assembly in containingSymbolResolution.OfType<IAssemblySymbol>())
29+
using var result = PooledArrayBuilder<IModuleSymbol>.GetInstance(containingSymbolResolution.SymbolCount);
30+
foreach (var symbol in containingSymbolResolution)
2931
{
32+
if (symbol is not IAssemblySymbol assembly)
33+
continue;
34+
3035
// Don't check ModuleIds for equality because in practice, no-one uses them,
3136
// and there is no way to set netmodule name programmatically using Roslyn
32-
result.AddValuesIfNotNull(assembly.Modules);
37+
var assemblyModules = assembly.Modules;
38+
if (assemblyModules is ImmutableArray<IModuleSymbol> modules)
39+
{
40+
// Avoid allocations if possible
41+
// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2136177
42+
result.AddValuesIfNotNull(modules);
43+
}
44+
else
45+
{
46+
// Visual Basic implementation of IAssemblySymbol.Modules relies on covariance of IEnumerable<T>, so
47+
// the preceding concrete type check will fail.
48+
result.AddValuesIfNotNull(assemblyModules);
49+
}
3350
}
3451

3552
return CreateResolution(result, $"({nameof(ModuleSymbolKey)} failed)", out failureReason);

0 commit comments

Comments
 (0)