Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active June 9, 2022 19:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrange/a7372cdf05356fa24cff6b25da7cb1e0 to your computer and use it in GitHub Desktop.
Save mrange/a7372cdf05356fa24cff6b25da7cb1e0 to your computer and use it in GitHub Desktop.
Testing Fusion vs Fission in F#
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
</ItemGroup>
</Project>
(*
// * Summary *
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.1741 (21H2)
Intel Core i5-3570K CPU 3.40GHz (Ivy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET SDK=6.0.300
[Host] : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT DEBUG
DefaultJob : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Allocated |
|-------------- |---------:|---------:|---------:|------:|--------:|---------:|----------:|
| Baseline | 15.43 us | 0.037 us | 0.035 us | 1.00 | 0.00 | - | - |
| BuiltIn | 15.40 us | 0.026 us | 0.025 us | 1.00 | 0.00 | - | - |
| Fusion | 68.65 us | 1.223 us | 1.085 us | 4.45 | 0.07 | 101.9287 | 320,032 B |
| Fusion_Struct | 95.14 us | 0.281 us | 0.263 us | 6.17 | 0.02 | - | - |
| Fission | 30.93 us | 0.059 us | 0.055 us | 2.00 | 0.01 | - | - |
*)
open BenchmarkDotNet
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
[<MemoryDiagnoser>]
type Benchmarks () =
class
let vs = List.init 10000 float
[<Benchmark(Baseline = true)>]
member x.Baseline () =
// Baseline is the basic for loop in F#
// assuming the foreach is implemented
// efficiently in F# this should give
// one of the better results
let mutable sum = 0.0
let mutable cnt = 0
for v in vs do
sum <- sum + v
cnt <- cnt + 1
sum / float cnt
[<Benchmark>]
member x.BuiltIn () =
// List.average is likely quick as well
vs |> List.average
[<Benchmark>]
member x.Fusion () =
// Using Fusion with reference tuples
// We expect this to incur some GC tax
let sumLength (sumAcc, cntAcc) (x : float) = (sumAcc + x, cntAcc + 1)
let sum, cnt = List.fold sumLength (0.0, 0) vs
sum / float cnt
[<Benchmark>]
member x.Fusion_Struct () =
// Using Fusion with struct tuples
// No GC tax expected but struct values have their own overhead
let sumLength (struct (sumAcc, cntAcc)) (x : float) = struct (sumAcc + x, cntAcc + 1)
let struct (sum, cnt) = List.fold sumLength (struct (0.0, 0)) vs
sum / float cnt
[<Benchmark>]
member x.Fission () =
// Using Fission
let sum = vs |> List.sum
let cnt = vs |> List.length
sum / float cnt
end
let _ = BenchmarkRunner.Run<Benchmarks>()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment