-
Notifications
You must be signed in to change notification settings - Fork 825
Description
I've noticed for some time now that quite a few functions that are called in many places are suboptimal in terms of performance. For instance, Array.create
, Array.init
, Array.concat
and Array.filter
can be improved upon with sometimes about 1.2-1.5x the speed, sometimes even manyfold (I got Array.replicate times source |> Array.concat
25X faster with a dedicated Array.repeat
, so that was a bit of cheating).
Sometimes such improvements relate specifically to large arrays, sometimes specifically to small ones. In line of that, String.xxx
functions that use StringBuilder
when replaced with ToCharArray()
instead improve by about 20-30%.
Before I start making a PR, which would certainly include showing the timings with BenchmarkDotNet for a variety of inputs, would such a PR be welcome? While nothing I tried is really complex, and what I tried is provably correct, as always with optimizations, they will increase the complexity of the code.
To get some idea, here's String.map
vs a very simple optimization of str.ToCharArray() |> Array.map mapper |> String
, which in many cases wins 40% (needs more input lengths comparisons, though, this was with 12-char string):
Method | Job | Jit | Platform | Runtime | Mean | Error | StdDev | Min | Max | Ratio | Rank | Gen 0 | Gen 1 | Gen 2 | Allocated |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
fastMap | Job-MACJMZ | LegacyJit | X64 | .NET 4.8 | 106.91ns | 1.069ns | 1.000ns | 105.31ns | 108.28ns | 0.65 | 1 | 0.0263 | - | - | 168 B |
stringMap | Job-MACJMZ | LegacyJit | X64 | .NET 4.8 | 164.29ns | 2.743ns | 2.291ns | 160.02ns | 169.34ns | 1.00 | 2 | 0.0315 | - | - | 201 B |
fastMap | Job-CZIGBL | LegacyJit | X86 | .NET 4.8 | 118.16ns | 1.094ns | 0.970ns | 116.88ns | 120.14ns | 0.64 | 1 | 0.0219 | - | - | 120 B |
stringMap | Job-CZIGBL | LegacyJit | X86 | .NET 4.8 | 184.93ns | 1.647ns | 1.540ns | 181.82ns | 187.86ns | 1.00 | 2 | 0.0233 | - | - | 128 B |
fastMap | Job-FZSSVS | RyuJit | X64 | .NET 4.8 | 95.61ns | 0.974ns | 0.911ns | 94.33ns | 97.43ns | 0.63 | 1 | 0.0261 | - | - | 168 B |
stringMap | Job-FZSSVS | RyuJit | X64 | .NET 4.8 | 151.22ns | 1.639ns | 1.368ns | 149.13ns | 154.09ns | 1.00 | 2 | 0.0315 | - | - | 201 B |
fastMap | Job-OXSCJZ | LegacyJit | X86 | .NET 4.6.1 | 117.96ns | 1.202ns | 1.065ns | 116.12ns | 119.48ns | 0.62 | 1 | 0.0227 | - | - | 120 B |
stringMap | Job-OXSCJZ | LegacyJit | X86 | .NET 4.6.1 | 191.32ns | 3.016ns | 2.673ns | 188.10ns | 196.17ns | 1.00 | 2 | 0.0237 | - | - | 128 B |