Skip to content

perf(Core): Reduce empty array allocations further#873

Merged
knocte merged 1 commit into
fsprojects:masterfrom
Numpsy:empty_collect
Jul 20, 2026
Merged

perf(Core): Reduce empty array allocations further#873
knocte merged 1 commit into
fsprojects:masterfrom
Numpsy:empty_collect

Conversation

@Numpsy

@Numpsy Numpsy commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Similar to #851

Calling Array.collect with an empty array results in the allocation of one zero length single dimensional array and one zero length two dimensional array, and as this function is called with huge frequency, this results in a substantial number of allocations.
The early exit also seems to avoid the allocation of a lambda in the empty case, reducing allocations further.

Benchmarks:

Before:

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated
LintParsedFile 845.7 ms 6.99 ms 6.19 ms 20000.0000 7000.0000 1000.0000 325.1 MB

After

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated
LintParsedFile 817.4 ms 4.79 ms 4.25 ms 14000.0000 5000.0000 1000.0000 229.87 MB

Similar to fsprojects#851

Calling Array.collect with an empty array results in the
allocation of one zero length single dimensional array and one
zero length two dimensional array, and as this function is
called with huge frequency, this results in a substantial
number of allocations.
The early exit also seems to avoid the allocation of a
lambda in the empty case, reducing allocations further.

Benchmarks:

Before:

| Method         | Mean     | Error   | StdDev  | Gen0       | Gen1      | Gen2      | Allocated |
|--------------- |---------:|--------:|--------:|-----------:|----------:|----------:|----------:|
| LintParsedFile | 845.7 ms | 6.99 ms | 6.19 ms | 20000.0000 | 7000.0000 | 1000.0000 |  325.1 MB |

After

| Method         | Mean     | Error   | StdDev  | Gen0       | Gen1      | Gen2      | Allocated |
|--------------- |---------:|--------:|--------:|-----------:|----------:|----------:|----------:|
| LintParsedFile | 817.4 ms | 4.79 ms | 4.25 ms | 14000.0000 | 5000.0000 | 1000.0000 | 229.87 MB |
@Numpsy

Numpsy commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Changes made after I got this from running the benchmark project through the Visual Studio alllocation profiler:

image

Near 1.4 million instances of WarningDetails[0] totalling ~33 million bytes, and a similar number of instances of WarningDetails[0][], and this would remove a big chunk of those. The allocation savings reported by BDN were more than I expected here as it seems that it might avoid some lambda/closure allocations as well.

The way that Array.collect seems to allocate two zero length arrays when called with a zero length input seems unfortunate to me, to the point where I wonder if it would be worth querying if it would be worth making it exit early to avoid at least one of those for an empty input.

@Numpsy
Numpsy marked this pull request as ready for review July 19, 2026 17:12
@knocte
knocte merged commit d56ab34 into fsprojects:master Jul 20, 2026
8 checks passed
@knocte

knocte commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Thanks @Numpsy !

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