Skip to content

Commit eaf41b4

Browse files
committed
Distribute COM interface friendly overloads across many classes
In full generation, the `FriendlyOverloadExtensions.g.cs` file was by far the largest (over 10MB in size). The C# compiler compiles types in parallel, so a very large type represents a huge unit of work that cannot be broken down into parallel compilations. It also means very large allocations for the string that renders the entire string. Splitting this up into one class per COM interface should help compilation performance, particularly in our full generation test.
1 parent 6ae12d1 commit eaf41b4

File tree

1 file changed

+21
-22
lines changed

1 file changed

+21
-22
lines changed

src/Microsoft.Windows.CsWin32/Generator.cs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ public class Generator : IDisposable
159159

160160
private static readonly SyntaxToken SemicolonWithLineFeed = TokenWithLineFeed(SyntaxKind.SemicolonToken);
161161
private static readonly IdentifierNameSyntax InlineArrayIndexerExtensionsClassName = IdentifierName("InlineArrayIndexerExtensions");
162-
private static readonly IdentifierNameSyntax ComInterfaceFriendlyExtensionsClassName = IdentifierName("FriendlyOverloadExtensions");
163162
private static readonly TypeSyntax SafeHandleTypeSyntax = IdentifierName("SafeHandle");
164163
private static readonly IdentifierNameSyntax IntPtrTypeSyntax = IdentifierName(nameof(IntPtr));
165164
private static readonly IdentifierNameSyntax UIntPtrTypeSyntax = IdentifierName(nameof(UIntPtr));
@@ -607,11 +606,7 @@ ClassDeclarationSyntax DeclarePInvokeClass(string fileNameKey) => ClassDeclarati
607606
result = result.Concat(new MemberDeclarationSyntax[] { inlineArrayIndexerExtensionsClass });
608607
}
609608

610-
ClassDeclarationSyntax comInterfaceFriendlyExtensionsClass = this.DeclareComInterfaceFriendlyExtensionsClass();
611-
if (comInterfaceFriendlyExtensionsClass.Members.Count > 0)
612-
{
613-
result = result.Concat(new MemberDeclarationSyntax[] { comInterfaceFriendlyExtensionsClass });
614-
}
609+
result = result.Concat(this.committedCode.ComInterfaceExtensions);
615610

616611
if (this.committedCode.TopLevelFields.Any())
617612
{
@@ -3429,14 +3424,6 @@ private ClassDeclarationSyntax DeclareInlineArrayIndexerExtensionsClass()
34293424
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute));
34303425
}
34313426

3432-
private ClassDeclarationSyntax DeclareComInterfaceFriendlyExtensionsClass()
3433-
{
3434-
return ClassDeclaration(ComInterfaceFriendlyExtensionsClassName.Identifier)
3435-
.AddMembers(this.committedCode.ComInterfaceExtensions.ToArray())
3436-
.WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)))
3437-
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute));
3438-
}
3439-
34403427
/// <summary>
34413428
/// Generates a type to represent a COM interface.
34423429
/// </summary>
@@ -3724,9 +3711,8 @@ StatementSyntax ThrowOnHRFailure(ExpressionSyntax hrExpression) => ExpressionSta
37243711
return null;
37253712
}
37263713

3727-
IdentifierNameSyntax ifaceName = interfaceAsSubtype
3728-
? NestedCOMInterfaceName
3729-
: IdentifierName(this.Reader.GetString(typeDef.Name));
3714+
string actualIfaceName = this.Reader.GetString(typeDef.Name);
3715+
IdentifierNameSyntax ifaceName = interfaceAsSubtype ? NestedCOMInterfaceName : IdentifierName(actualIfaceName);
37303716
TypeSyntaxSettings typeSettings = this.comSignatureTypeSettings;
37313717

37323718
// It is imperative that we generate methods for all base interfaces as well, ahead of any implemented by *this* interface.
@@ -3932,7 +3918,20 @@ StatementSyntax ThrowOnHRFailure(ExpressionSyntax hrExpression) => ExpressionSta
39323918

39333919
// Only add overloads to instance collections after everything else is done,
39343920
// so we don't leave extension methods behind if we fail to generate the target interface.
3935-
this.volatileCode.AddComInterfaceExtension(friendlyOverloads);
3921+
if (friendlyOverloads.Count > 0)
3922+
{
3923+
string ns = this.Reader.GetString(typeDef.Namespace);
3924+
if (this.TryStripCommonNamespace(ns, out string? strippedNamespace))
3925+
{
3926+
ns = strippedNamespace;
3927+
}
3928+
3929+
ClassDeclarationSyntax friendlyOverloadClass = ClassDeclaration(Identifier($"{ns.Replace('.', '_')}_{actualIfaceName}_Extensions"))
3930+
.WithMembers(List<MemberDeclarationSyntax>(friendlyOverloads))
3931+
.WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)))
3932+
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute));
3933+
this.volatileCode.AddComInterfaceExtension(friendlyOverloadClass);
3934+
}
39363935

39373936
return ifaceDeclaration;
39383937
}
@@ -6761,7 +6760,7 @@ private class GeneratedCode
67616760

67626761
private readonly List<MethodDeclarationSyntax> inlineArrayIndexerExtensionsMembers = new();
67636762

6764-
private readonly List<MethodDeclarationSyntax> comInterfaceFriendlyExtensionsMembers = new();
6763+
private readonly List<ClassDeclarationSyntax> comInterfaceFriendlyExtensionsMembers = new();
67656764

67666765
private bool generating;
67676766

@@ -6784,7 +6783,7 @@ internal GeneratedCode(GeneratedCode parent)
67846783

67856784
internal IEnumerable<MemberDeclarationSyntax> GeneratedTopLevelTypes => this.specialTypes.Values.Where(st => st.TopLevel).Select(st => st.Type);
67866785

6787-
internal IEnumerable<MethodDeclarationSyntax> ComInterfaceExtensions => this.comInterfaceFriendlyExtensionsMembers;
6786+
internal IReadOnlyCollection<ClassDeclarationSyntax> ComInterfaceExtensions => this.comInterfaceFriendlyExtensionsMembers;
67886787

67896788
internal IEnumerable<MethodDeclarationSyntax> InlineArrayIndexerExtensions => this.inlineArrayIndexerExtensionsMembers;
67906789

@@ -6866,13 +6865,13 @@ internal void AddInlineArrayIndexerExtension(MethodDeclarationSyntax inlineIndex
68666865
}
68676866
}
68686867

6869-
internal void AddComInterfaceExtension(MethodDeclarationSyntax extension)
6868+
internal void AddComInterfaceExtension(ClassDeclarationSyntax extension)
68706869
{
68716870
this.ThrowIfNotGenerating();
68726871
this.comInterfaceFriendlyExtensionsMembers.Add(extension);
68736872
}
68746873

6875-
internal void AddComInterfaceExtension(IEnumerable<MethodDeclarationSyntax> extension)
6874+
internal void AddComInterfaceExtension(IEnumerable<ClassDeclarationSyntax> extension)
68766875
{
68776876
this.ThrowIfNotGenerating();
68786877
this.comInterfaceFriendlyExtensionsMembers.AddRange(extension);

0 commit comments

Comments
 (0)