Skip to content

feat: create an overload for Any( SyntaxTriviaList to prevent allocations#1485

Merged
belav merged 2 commits intobelav:mainfrom
TimothyMakkison:trivia_list_enumerator
Feb 21, 2025
Merged

feat: create an overload for Any( SyntaxTriviaList to prevent allocations#1485
belav merged 2 commits intobelav:mainfrom
TimothyMakkison:trivia_list_enumerator

Conversation

@TimothyMakkison
Copy link
Copy Markdown
Contributor

@TimothyMakkison TimothyMakkison commented Feb 17, 2025

Creates an extension method that overloads Any(this SyntaxTriviaList) this uses the struct SyntaxTriviaList.Enumerator to iterate, instead of allocating the class SyntaxTriviaList.EnumeratorImpl : IEnumerator<SyntaxTrivia> and boxing SyntaxTrviaList.

Saves around 11% of memory aka 11MB on the benchmark.

Benchmarks

Before

Method Mean Error StdDev Median Gen0 Gen1 Gen2 Allocated
Default_CodeFormatter 187,771.22 us 3,718.757 us 6,705.686 us 187,214.50 us 11000.0000 4000.0000 1000.0000 98124.57 KB
Default_SyntaxNodeComparer 1,920.62 us 77.064 us 227.225 us 1,840.56 us 66.4063 15.6250 - 643.28 KB
IsCodeBasicallyEqual_SyntaxNodeComparer 97.11 us 3.195 us 9.421 us 96.33 us 10.7422 1.3428 - 99.02 KB

After

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated
Default_CodeFormatter 180,664.34 us 3,555.331 us 6,037.222 us 10000.0000 4000.0000 1000.0000 87296.88 KB
Default_SyntaxNodeComparer 2,315.61 us 105.286 us 310.439 us 66.4063 15.6250 - 643.28 KB
IsCodeBasicallyEqual_SyntaxNodeComparer 84.32 us 1.638 us 2.297 us 10.7422 1.3428 - 99.02 KB

belav pushed a commit that referenced this pull request Feb 21, 2025
…#1486)

Similar to #1485, use a manual `foreach` where loop to prevent boxing of
`SyntaxTriviaList`, `SyntaxTriviaList.EnumeratorImpl` and
`WhereIterator`.

### Before

![image](https://github.com/user-attachments/assets/5da8a77a-e7fe-4852-b6b8-6849ebb6c469)

### After

![image](https://github.com/user-attachments/assets/bcbedb56-e444-45e3-89d0-19d868840c34)
@belav belav enabled auto-merge (squash) February 21, 2025 16:06
@belav belav merged commit 0a62c26 into belav:main Feb 21, 2025
TimothyMakkison added a commit to TimothyMakkison/csharpier that referenced this pull request Feb 24, 2025
…belav#1486)

Similar to belav#1485, use a manual `foreach` where loop to prevent boxing of
`SyntaxTriviaList`, `SyntaxTriviaList.EnumeratorImpl` and
`WhereIterator`.

### Before

![image](https://github.com/user-attachments/assets/5da8a77a-e7fe-4852-b6b8-6849ebb6c469)

### After

![image](https://github.com/user-attachments/assets/bcbedb56-e444-45e3-89d0-19d868840c34)
TimothyMakkison added a commit to TimothyMakkison/csharpier that referenced this pull request Feb 24, 2025
…ations (belav#1485)

Creates an extension method that overloads `Any(this SyntaxTriviaList)`
this uses the struct `SyntaxTriviaList.Enumerator` to iterate, instead
of allocating the class `SyntaxTriviaList.EnumeratorImpl :
IEnumerator<SyntaxTrivia>` and boxing `SyntaxTrviaList`.

Saves around 11% of memory aka 11MB on the benchmark.

## Benchmarks
### Before
| Method | Mean | Error | StdDev | Median | Gen0 | Gen1 | Gen2 |
Allocated |
|----------------------------------------
|--------------:|-------------:|-------------:|--------------:|-----------:|----------:|----------:|------------:|
| Default_CodeFormatter | 187,771.22 us | 3,718.757 us | 6,705.686 us |
187,214.50 us | 11000.0000 | 4000.0000 | 1000.0000 | 98124.57 KB |
| Default_SyntaxNodeComparer | 1,920.62 us | 77.064 us | 227.225 us |
1,840.56 us | 66.4063 | 15.6250 | - | 643.28 KB |
| IsCodeBasicallyEqual_SyntaxNodeComparer | 97.11 us | 3.195 us | 9.421
us | 96.33 us | 10.7422 | 1.3428 | - | 99.02 KB |


### After
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated |
|----------------------------------------
|--------------:|-------------:|-------------:|-----------:|----------:|----------:|------------:|
| Default_CodeFormatter | 180,664.34 us | 3,555.331 us | 6,037.222 us |
10000.0000 | 4000.0000 | 1000.0000 | 87296.88 KB |
| Default_SyntaxNodeComparer | 2,315.61 us | 105.286 us | 310.439 us |
66.4063 | 15.6250 | - | 643.28 KB |
| IsCodeBasicallyEqual_SyntaxNodeComparer | 84.32 us | 1.638 us | 2.297
us | 10.7422 | 1.3428 | - | 99.02 KB |

Co-authored-by: Bela VanderVoort <[email protected]>
belav added a commit that referenced this pull request Dec 25, 2025
…#1703)

Semi reverts #1572 which overwrote #1485, I assume this was accidental.
I noticed that you prefer explicit `Enumerable.Any` usage, should I
convert this PR to use `ListExtensions.Any`?


## Benchmarks
Saves around 15% of memory usage
### Before
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|--------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 128.0 ms | 2.44 ms | 3.43 ms | 3000.0000
| 1000.0000 | 34.57 MB |
| Default_CodeFormatter_Complex | 260.3 ms | 5.11 ms | 7.17 ms |
5000.0000 | 2000.0000 | 53.05 MB |


### After
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|---------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 126.0 ms | 2.27 ms | 5.45 ms | 2000.0000
| 1000.0000 | 28.02 MB |
| Default_CodeFormatter_Complex | 245.2 ms | 4.63 ms | 10.44 ms |
4000.0000 | 2000.0000 | 43.88 MB |

Co-authored-by: Bela VanderVoort <[email protected]>
belav added a commit that referenced this pull request Dec 31, 2025
…#1703)

Semi reverts #1572 which overwrote #1485, I assume this was accidental.
I noticed that you prefer explicit `Enumerable.Any` usage, should I
convert this PR to use `ListExtensions.Any`?


## Benchmarks
Saves around 15% of memory usage
### Before
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|--------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 128.0 ms | 2.44 ms | 3.43 ms | 3000.0000
| 1000.0000 | 34.57 MB |
| Default_CodeFormatter_Complex | 260.3 ms | 5.11 ms | 7.17 ms |
5000.0000 | 2000.0000 | 53.05 MB |


### After
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|---------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 126.0 ms | 2.27 ms | 5.45 ms | 2000.0000
| 1000.0000 | 28.02 MB |
| Default_CodeFormatter_Complex | 245.2 ms | 4.63 ms | 10.44 ms |
4000.0000 | 2000.0000 | 43.88 MB |

Co-authored-by: Bela VanderVoort <[email protected]>
belav added a commit that referenced this pull request Feb 20, 2026
…#1703)

Semi reverts #1572 which overwrote #1485, I assume this was accidental.
I noticed that you prefer explicit `Enumerable.Any` usage, should I
convert this PR to use `ListExtensions.Any`?

## Benchmarks
Saves around 15% of memory usage
### Before
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|--------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 128.0 ms | 2.44 ms | 3.43 ms | 3000.0000
| 1000.0000 | 34.57 MB |
| Default_CodeFormatter_Complex | 260.3 ms | 5.11 ms | 7.17 ms |
5000.0000 | 2000.0000 | 53.05 MB |

### After
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|---------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 126.0 ms | 2.27 ms | 5.45 ms | 2000.0000
| 1000.0000 | 28.02 MB |
| Default_CodeFormatter_Complex | 245.2 ms | 4.63 ms | 10.44 ms |
4000.0000 | 2000.0000 | 43.88 MB |

Co-authored-by: Bela VanderVoort <[email protected]>
belav added a commit that referenced this pull request Mar 12, 2026
…#1703)

Semi reverts #1572 which overwrote #1485, I assume this was accidental.
I noticed that you prefer explicit `Enumerable.Any` usage, should I
convert this PR to use `ListExtensions.Any`?

## Benchmarks
Saves around 15% of memory usage
### Before
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|--------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 128.0 ms | 2.44 ms | 3.43 ms | 3000.0000
| 1000.0000 | 34.57 MB |
| Default_CodeFormatter_Complex | 260.3 ms | 5.11 ms | 7.17 ms |
5000.0000 | 2000.0000 | 53.05 MB |

### After
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|---------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 126.0 ms | 2.27 ms | 5.45 ms | 2000.0000
| 1000.0000 | 28.02 MB |
| Default_CodeFormatter_Complex | 245.2 ms | 4.63 ms | 10.44 ms |
4000.0000 | 2000.0000 | 43.88 MB |

Co-authored-by: Bela VanderVoort <[email protected]>
belav added a commit that referenced this pull request Apr 4, 2026
…#1703)

Semi reverts #1572 which overwrote #1485, I assume this was accidental.
I noticed that you prefer explicit `Enumerable.Any` usage, should I
convert this PR to use `ListExtensions.Any`?

## Benchmarks
Saves around 15% of memory usage
### Before
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|--------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 128.0 ms | 2.44 ms | 3.43 ms | 3000.0000
| 1000.0000 | 34.57 MB |
| Default_CodeFormatter_Complex | 260.3 ms | 5.11 ms | 7.17 ms |
5000.0000 | 2000.0000 | 53.05 MB |

### After
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------------------------------
|---------:|--------:|---------:|----------:|----------:|----------:|
| Default_CodeFormatter_Tests | 126.0 ms | 2.27 ms | 5.45 ms | 2000.0000
| 1000.0000 | 28.02 MB |
| Default_CodeFormatter_Complex | 245.2 ms | 4.63 ms | 10.44 ms |
4000.0000 | 2000.0000 | 43.88 MB |

Co-authored-by: Bela VanderVoort <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants