Performance Optimization
BenchmarkDotNet, dotnet-trace, dotnet-counters, PerfView, Rider/VS profilers Choose collections wisely
Arrays and ResizeArray/Dictionary for hot paths; avoid @ in loops; avoid repeated List.item
Struct tuples (struct (a, b)), struct records/unions, ValueOption, [<InlineIfLambda>]
Inline small generic functions to avoid boxing and enable specialization
Slice without copying; stackalloc via NativePtr.stackalloc Seq vs List/Array
Seq has per-element overhead; materialize hot data Tail recursion and loops
Avoid deep non-tail recursion on large inputs Mutable locals inside functions Fine for performance when encapsulated
task { } over async { } in hot I/O paths Custom [<CustomEquality>] or [<ReferenceEquality>] when structural equality is expensive StringBuilder, String.concat Release builds, ReadyToRun, Native AOT
dotnet publish -c Release -p:PublishReadyToRun=true / -p:PublishAot=true (check library compatibility)
#r "nuget: BenchmarkDotNet"
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
[<MemoryDiagnoser>]
type ListVsArray() =
let data = [| 1 .. 10_000 |]
let list = List.ofArray data
[<Benchmark>] member _.ListSum() = List.sum list
[<Benchmark>] member _.ArraySum() = Array.sum data
[<Benchmark>] member _.SeqSum() = Seq.sum data
// BenchmarkRunner.Run<ListVsArray>() |> ignore (run from a Release console app)
// [<InlineIfLambda>] lets the compiler inline lambda arguments
let inline iterFast ([<InlineIfLambda>] f: int -> unit) (arr: int[]) =
for i in 0 .. arr.Length - 1 do f arr[i]