Skip to content

Commit 5a9e32d

Browse files
perf: use ValueListBuilder<T> for constant buffers (#1529)
Follow on from #1502, using `ValueListBuilder` to replace known `List<Doc>` sizes. - Most of these changes aren't measurable in the benchmarks, many are insignificant, although I suspect this is partly due to the limited code found in the benchmark file. - This PR will increase the performance benefits of #1524 @belav what do you think the best way of replacing a list that uses a collection initializer is? I can either add the items directly into the scratch buffer and manually update `Length` ```C# var docs = new ValueListBuilder<Doc> ([ Modifiers.Print(node.Modifiers, context), Token.Print(node.DelegateKeyword, context), null,null ]); docs.Length = 2; ``` Or create the buffer and then append the items via params. ```C# var docs = new ValueListBuilder<Doc>([null, null, null, null]); docs.Append( Modifiers.Print(node.Modifiers, context), Token.Print(node.DelegateKeyword, context) ); ``` Or Append each item ```C# var docs = new ValueListBuilder<Doc>([null, null, null, null]); docs.Append(Modifiers.Print(node.Modifiers, context)); docs.Append(Token.Print(node.DelegateKeyword, context)); ``` --------- Co-authored-by: Bela VanderVoort <[email protected]>
1 parent a16b085 commit 5a9e32d

24 files changed

+175
-184
lines changed

Src/CSharpier/DocTypes/Doc.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ public static Doc Concat(List<Doc> contents) =>
5656

5757
public static Doc Concat(params Doc[] contents) => new Concat(contents);
5858

59+
public static Doc Concat(ref ValueListBuilder<Doc> contents)
60+
{
61+
return contents.Length switch
62+
{
63+
0 => Null,
64+
1 => contents[0],
65+
_ => new Concat(contents.AsSpan().ToArray()),
66+
};
67+
}
68+
5969
public static Doc Join(Doc separator, IEnumerable<Doc> enumerable)
6070
{
6171
var docs = new List<Doc>();

Src/CSharpier/SyntaxPrinter/AttributeLists.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ PrintingContext context
1313
return Doc.Null;
1414
}
1515

16-
var docs = new List<Doc>();
16+
var docs = new ValueListBuilder<Doc>([null, null]);
1717
Doc separator = node
1818
is TypeParameterSyntax
1919
or ParameterSyntax
@@ -22,13 +22,15 @@ or AccessorDeclarationSyntax
2222
? Doc.Line
2323
: Doc.HardLine;
2424

25-
docs.Add(Doc.Join(separator, attributeLists.Select(o => AttributeList.Print(o, context))));
25+
docs.Append(
26+
Doc.Join(separator, attributeLists.Select(o => AttributeList.Print(o, context)))
27+
);
2628

2729
if (node is not (ParameterSyntax or TypeParameterSyntax))
2830
{
29-
docs.Add(separator);
31+
docs.Append(separator);
3032
}
3133

32-
return Doc.Concat(docs);
34+
return Doc.Concat(ref docs);
3335
}
3436
}

Src/CSharpier/SyntaxPrinter/SeparatedSyntaxList.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,7 @@ private static Doc Print<T>(
144144
docs.Append(unFormattedCode.ToString().Trim());
145145
}
146146

147-
var output = docs.Length switch
148-
{
149-
0 => Doc.Null,
150-
1 => docs[0],
151-
_ => Doc.Concat(docs.AsSpan().ToArray()),
152-
};
147+
var output = Doc.Concat(ref docs);
153148
docs.Dispose();
154149

155150
return output;

Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/AnonymousMethodExpression.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@ internal static class AnonymousMethodExpression
44
{
55
public static Doc Print(AnonymousMethodExpressionSyntax node, PrintingContext context)
66
{
7-
var docs = new List<Doc>
8-
{
9-
Modifiers.Print(node.Modifiers, context),
10-
Token.Print(node.DelegateKeyword, context),
11-
};
7+
var docs = new ValueListBuilder<Doc>([null, null, null, null]);
8+
docs.Append(Modifiers.Print(node.Modifiers, context));
9+
docs.Append(Token.Print(node.DelegateKeyword, context));
1210

1311
if (node.ParameterList != null)
1412
{
15-
docs.Add(ParameterList.Print(node.ParameterList, context));
13+
docs.Append(ParameterList.Print(node.ParameterList, context));
1614
}
1715

18-
docs.Add(Block.Print(node.Block, context));
16+
docs.Append(Block.Print(node.Block, context));
1917

20-
return Doc.Concat(docs);
18+
return Doc.Concat(ref docs);
2119
}
2220
}

Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/AnonymousObjectMemberDeclarator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ internal static class AnonymousObjectMemberDeclarator
44
{
55
public static Doc Print(AnonymousObjectMemberDeclaratorSyntax node, PrintingContext context)
66
{
7-
var docs = new List<Doc>();
7+
var docs = new ValueListBuilder<Doc>([null, null, null, null]);
88
if (
99
node.Parent is AnonymousObjectCreationExpressionSyntax parent
1010
&& node != parent.Initializers.First()
1111
)
1212
{
13-
docs.Add(ExtraNewLines.Print(node));
13+
docs.Append(ExtraNewLines.Print(node));
1414
}
1515

1616
if (node.NameEquals != null)
1717
{
18-
docs.Add(Token.PrintWithSuffix(node.NameEquals.Name.Identifier, " ", context));
19-
docs.Add(Token.PrintWithSuffix(node.NameEquals.EqualsToken, " ", context));
18+
docs.Append(Token.PrintWithSuffix(node.NameEquals.Name.Identifier, " ", context));
19+
docs.Append(Token.PrintWithSuffix(node.NameEquals.EqualsToken, " ", context));
2020
}
21-
docs.Add(Node.Print(node.Expression, context));
22-
return Doc.Concat(docs);
21+
docs.Append(Node.Print(node.Expression, context));
22+
return Doc.Concat(ref docs);
2323
}
2424
}

Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/Argument.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ public static Doc Print(ArgumentSyntax node, PrintingContext context)
99

1010
public static Doc PrintModifiers(ArgumentSyntax node, PrintingContext context)
1111
{
12-
var docs = new List<Doc>(2);
12+
var docs = new ValueListBuilder<Doc>([null, null]);
1313
if (node.NameColon != null)
1414
{
15-
docs.Add(BaseExpressionColon.Print(node.NameColon, context));
15+
docs.Append(BaseExpressionColon.Print(node.NameColon, context));
1616
}
1717

1818
if (node.RefKindKeyword.RawSyntaxKind() != SyntaxKind.None)
1919
{
20-
docs.Add(Token.PrintWithSuffix(node.RefKindKeyword, " ", context));
20+
docs.Append(Token.PrintWithSuffix(node.RefKindKeyword, " ", context));
2121
}
2222

23-
return Doc.Concat(docs);
23+
return Doc.Concat(ref docs);
2424
}
2525
}

Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/AttributeList.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ public static Doc Print(AttributeListSyntax node, PrintingContext context)
99
return CSharpierIgnore.PrintWithoutFormatting(node, context).Trim();
1010
}
1111

12-
var docs = new List<Doc>();
12+
var docs = new ValueListBuilder<Doc>([null, null, null, null, null, null, null]);
1313
if (
1414
node.Parent is CompilationUnitSyntax compilationUnitSyntax
1515
&& compilationUnitSyntax.AttributeLists.First() != node
1616
)
1717
{
18-
docs.Add(ExtraNewLines.Print(node));
18+
docs.Append(ExtraNewLines.Print(node));
1919
}
2020

21-
docs.Add(Token.Print(node.OpenBracketToken, context));
21+
docs.Append(Token.Print(node.OpenBracketToken, context));
2222
if (node.Target != null)
2323
{
24-
docs.Add(
24+
docs.Append(
2525
Token.Print(node.Target.Identifier, context),
2626
Token.PrintWithSuffix(node.Target.ColonToken, " ", context)
2727
);
@@ -72,17 +72,19 @@ node.Parent is CompilationUnitSyntax compilationUnitSyntax
7272
context
7373
);
7474

75-
docs.Add(
75+
docs.Append(
7676
node.Attributes.Count > 1
7777
? Doc.Indent(Doc.SoftLine, printSeparatedSyntaxList)
7878
: printSeparatedSyntaxList
7979
);
8080

81-
docs.Add(
82-
node.Attributes.Count > 1 ? Doc.SoftLine : Doc.Null,
83-
Token.Print(node.CloseBracketToken, context)
84-
);
81+
if (node.Attributes.Count > 1)
82+
{
83+
docs.Append(Doc.SoftLine);
84+
}
85+
86+
docs.Append(Token.Print(node.CloseBracketToken, context));
8587

86-
return Doc.Group(docs);
88+
return Doc.Group(docs.AsSpan().ToArray());
8789
}
8890
}

Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BaseFieldDeclaration.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ internal static class BaseFieldDeclaration
44
{
55
public static Doc Print(BaseFieldDeclarationSyntax node, PrintingContext context)
66
{
7-
var docs = new List<Doc>
8-
{
9-
AttributeLists.Print(node, node.AttributeLists, context),
10-
Modifiers.PrintSorted(node.Modifiers, context),
11-
};
7+
var docs = new ValueListBuilder<Doc>([null, null, null, null, null]);
8+
docs.Append(AttributeLists.Print(node, node.AttributeLists, context));
9+
docs.Append(Modifiers.PrintSorted(node.Modifiers, context));
1210
if (node is EventFieldDeclarationSyntax eventFieldDeclarationSyntax)
1311
{
14-
docs.Add(Token.PrintWithSuffix(eventFieldDeclarationSyntax.EventKeyword, " ", context));
12+
docs.Append(
13+
Token.PrintWithSuffix(eventFieldDeclarationSyntax.EventKeyword, " ", context)
14+
);
1515
}
1616

17-
docs.Add(
17+
docs.Append(
1818
VariableDeclaration.Print(node.Declaration, context),
1919
Token.Print(node.SemicolonToken, context)
2020
);
21-
return Doc.Concat(docs);
21+
return Doc.Concat(ref docs);
2222
}
2323
}

Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/BasePropertyDeclaration.cs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,9 @@ public static Doc Print(BasePropertyDeclarationSyntax node, PrintingContext cont
3838
semicolonToken = eventDeclarationSyntax.SemicolonToken;
3939
}
4040

41-
var docs = new List<Doc> { AttributeLists.Print(node, node.AttributeLists, context) };
42-
4341
return Doc.Group(
4442
Doc.Concat(
45-
Doc.Concat(docs),
43+
AttributeLists.Print(node, node.AttributeLists, context),
4644
Modifiers.PrintSorted(node.Modifiers, context),
4745
eventKeyword,
4846
Node.Print(node.Type, context),
@@ -112,7 +110,7 @@ private static Doc PrintAccessorDeclarationSyntax(
112110
PrintingContext context
113111
)
114112
{
115-
var docs = new List<Doc>();
113+
var docs = new ValueListBuilder<Doc>([null, null, null, null, null, null]);
116114
if (
117115
node.AttributeLists.Count > 1
118116
|| node.Body != null
@@ -123,28 +121,28 @@ PrintingContext context
123121
)
124122
)
125123
{
126-
docs.Add(Doc.HardLine);
124+
docs.Append(Doc.HardLine);
127125
}
128126
else
129127
{
130-
docs.Add(separator);
128+
docs.Append(separator);
131129
}
132130

133-
docs.Add(AttributeLists.Print(node, node.AttributeLists, context));
134-
docs.Add(Modifiers.PrintSorted(node.Modifiers, context));
135-
docs.Add(Token.Print(node.Keyword, context));
131+
docs.Append(AttributeLists.Print(node, node.AttributeLists, context));
132+
docs.Append(Modifiers.PrintSorted(node.Modifiers, context));
133+
docs.Append(Token.Print(node.Keyword, context));
136134

137135
if (node.Body != null)
138136
{
139-
docs.Add(Block.Print(node.Body, context));
137+
docs.Append(Block.Print(node.Body, context));
140138
}
141139
else if (node.ExpressionBody != null)
142140
{
143-
docs.Add(ArrowExpressionClause.Print(node.ExpressionBody, context));
141+
docs.Append(ArrowExpressionClause.Print(node.ExpressionBody, context));
144142
}
145143

146-
docs.Add(Token.Print(node.SemicolonToken, context));
144+
docs.Append(Token.Print(node.SemicolonToken, context));
147145

148-
return Doc.Concat(docs);
146+
return Doc.Concat(ref docs);
149147
}
150148
}

Src/CSharpier/SyntaxPrinter/SyntaxNodePrinters/DelegateDeclaration.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,25 @@ internal static class DelegateDeclaration
44
{
55
public static Doc Print(DelegateDeclarationSyntax node, PrintingContext context)
66
{
7-
var docs = new List<Doc>
8-
{
9-
AttributeLists.Print(node, node.AttributeLists, context),
10-
Modifiers.PrintSorted(node.Modifiers, context),
11-
Token.PrintWithSuffix(node.DelegateKeyword, " ", context),
12-
Node.Print(node.ReturnType, context),
13-
{ " ", Token.Print(node.Identifier, context) },
14-
};
7+
var docs = new ValueListBuilder<Doc>(
8+
[null, null, null, null, null, null, null, null, null, null]
9+
);
10+
docs.Append(AttributeLists.Print(node, node.AttributeLists, context));
11+
docs.Append(Modifiers.PrintSorted(node.Modifiers, context));
12+
docs.Append(Token.PrintWithSuffix(node.DelegateKeyword, " ", context));
13+
docs.Append(Node.Print(node.ReturnType, context));
14+
docs.Append(" ");
15+
docs.Append(Token.Print(node.Identifier, context));
16+
1517
if (node.TypeParameterList != null)
1618
{
17-
docs.Add(Node.Print(node.TypeParameterList, context));
19+
docs.Append(Node.Print(node.TypeParameterList, context));
1820
}
19-
docs.Add(
21+
docs.Append(
2022
Node.Print(node.ParameterList, context),
2123
ConstraintClauses.Print(node.ConstraintClauses, context),
2224
Token.Print(node.SemicolonToken, context)
2325
);
24-
return Doc.Concat(docs);
26+
return Doc.Concat(ref docs);
2527
}
2628
}

0 commit comments

Comments
 (0)