Use FSharp.Core.Extended
Before
| Method | Mean | Error | StdDev | Rank | Gen0 | Gen1 | Allocated |
|------- |---------:|---------:|---------:|-----:|---------:|---------:|----------:|
| Format | 60.39 ms | 1.102 ms | 1.312 ms | 1 | 888.8889 | 333.3333 | 155.13 MB |
After
| Method | Mean | Error | StdDev | Rank | Gen0 | Gen1 | Allocated |
|------- |---------:|---------:|---------:|-----:|---------:|---------:|----------:|
| Format | 60.51 ms | 0.489 ms | 0.458 ms | 1 | 888.8889 | 333.3333 | 155.13 MB |
It didn't really do anything for this repo. Maybe I missed something in setting this up, although we probably don't use any of the optimized APIs.
//cc @vzarytovskii
Yeah, fair. I will look at the fantomas codebase and see what it can benefit from.
Does it need a open FSharp.Core.Extended.Collections to use the alternate functions?
Yeah, fair. I will look at the fantomas codebase and see what it can benefit from.
A quick attempt at profiling suggests that a version of Seq.tryHead using ValueOption might shave off some Option allocations in a few places fwiw
Does it need a
open FSharp.Core.Extended.Collectionsto use the alternate functions?Yeah, fair. I will look at the fantomas codebase and see what it can benefit from.
A quick attempt at profiling suggests that a version of Seq.tryHead using ValueOption might shave off some Option allocations in a few places fwiw
That's on my list, however on latest runtime, reference types which do not escape the stack frame can be lifted to be allocated on stack. So this might be an improvement even without that change.
Does the automatic stack allocation require tryHead to be inline to remove the allocations in .NET 9?
A small obervation when I ran the VS memory profiler on the 'Format' benchmark in case it's of interest - it says there are 67781 allocations of 0 length arrays of TriviaNode -
Those all appear to be from creating Queues with an explicit 0 capacity at https://github.com/fsprojects/fantomas/blob/bc7402c39c56fc7cf996e3c2243cff6f3d279618/src/Fantomas.Core/SyntaxOak.fs#L34 because it appears that Queue always creates a new array when a capacity is specified, even if the capacity is 0, and just using the default constructor instead there reduces the reported memory allocations in the benchmark from 155.09 MB to 153.53 MB
On the related thought, would the Array.choose |> Array.tryHead at https://github.com/fsprojects/fantomas/blob/d21ab681da1328407aa4d607e67e1174d6214629/src/Fantomas.Core/Trivia.fs#L161 work as Array.tryPick ?
On the related thought, would the
Array.choose |> Array.tryHeadathttps://github.com/fsprojects/fantomas/blob/d21ab681da1328407aa4d607e67e1174d6214629/src/Fantomas.Core/Trivia.fs#L161
work as
Array.tryPick?
Probably, would accept a PR, but I doubt it will have much impact.
Saves 0.37MB of memory allocations in the benchmark project according to BDN, which is admitedly small compared to 155MB overall
Going to close this, but would accept/consider a new PR with this idea.