From 3babbba6d62b48a34a0c427daa7fc9a50f5be795 Mon Sep 17 00:00:00 2001 From: Smaug123 Date: Tue, 12 Dec 2023 20:57:18 +0000 Subject: [PATCH] Bench --- .../AdventOfCode2023.FSharp.Bench.fsproj | 22 ++ .../AdventOfCode2023.FSharp.Bench/Inputs.fs | 19 ++ .../AdventOfCode2023.FSharp.Bench/Program.fs | 70 +++++++ .../AdventOfCode2023.FSharp.Bench/Run.fs | 190 ++++++++++++++++++ .../AdventOfCode2023.FSharp.sln | 6 + README.md | 104 +++++++++- 6 files changed, 402 insertions(+), 9 deletions(-) create mode 100644 AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/AdventOfCode2023.FSharp.Bench.fsproj create mode 100644 AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Inputs.fs create mode 100644 AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Program.fs create mode 100644 AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Run.fs diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/AdventOfCode2023.FSharp.Bench.fsproj b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/AdventOfCode2023.FSharp.Bench.fsproj new file mode 100644 index 0000000..f71efee --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/AdventOfCode2023.FSharp.Bench.fsproj @@ -0,0 +1,22 @@ + + + + Exe + net8.0 + + + + + + + + + + + + + + + + + diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Inputs.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Inputs.fs new file mode 100644 index 0000000..5646ffa --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Inputs.fs @@ -0,0 +1,19 @@ +namespace AdventOfCode2023 + +open System.IO +open System.Reflection + +[] +module Inputs = + let days = + let mutable dir = Assembly.GetEntryAssembly().Location |> FileInfo |> _.Directory + + while not (dir.EnumerateDirectories () |> Seq.exists (fun i -> i.Name = "inputs")) do + dir <- dir.Parent + + if isNull dir then + failwith "reached root of filesystem without finding inputs dir" + + Array.init 12 (fun day -> Path.Combine (dir.FullName, "inputs", $"day%i{day + 1}.txt") |> File.ReadAllText) + + let inline day (i : int) = days.[i - 1] diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Program.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Program.fs new file mode 100644 index 0000000..8a2d560 --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Program.fs @@ -0,0 +1,70 @@ +namespace AdventOfCode2023 + +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Configs +open BenchmarkDotNet.Running + +module Benchmarks = + type Benchmark1To5 () = + [] + member _.Setup () = Run.shouldWrite <- false + + [] + member val Day = 0 with get, set + + [] + member val IsPartOne = false with get, set + + [] + member this.Benchmark () : unit = + Run.allRuns.[this.Day - 1] (not this.IsPartOne) (Inputs.day this.Day) + + [] + member _.Cleanup () = Run.shouldWrite <- true + + + type Benchmark6To10 () = + [] + member _.Setup () = Run.shouldWrite <- false + + [] + member val Day = 0 with get, set + + [] + member val IsPartOne = false with get, set + + [] + member this.Benchmark () : unit = + Run.allRuns.[this.Day - 1] (not this.IsPartOne) (Inputs.day this.Day) + + [] + member _.Cleanup () = Run.shouldWrite <- true + + type Benchmark11To15 () = + [] + member _.Setup () = Run.shouldWrite <- false + + [] + member val Day = 0 with get, set + + [] + member val IsPartOne = false with get, set + + [] + member this.Benchmark () : unit = + Run.allRuns.[this.Day - 1] (not this.IsPartOne) (Inputs.day this.Day) + + [] + member _.Cleanup () = Run.shouldWrite <- true + +module Program = + + [] + let main args = + let config = + ManualConfig.Create(DefaultConfig.Instance).WithOptions ConfigOptions.DisableOptimizationsValidator + + let _summary = BenchmarkRunner.Run config + let _summary = BenchmarkRunner.Run config + let _summary = BenchmarkRunner.Run config + 0 diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Run.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Run.fs new file mode 100644 index 0000000..d3ffbe0 --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Run.fs @@ -0,0 +1,190 @@ +namespace AdventOfCode2023 + +#if DEBUG +#else +#nowarn "9" +#endif + +open System + +[] +module Run = + let mutable shouldWrite = true + + let day1 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day1.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day1.part2 input + + if shouldWrite then + Console.WriteLine output + + let day2 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day2.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day2.part2 input + + if shouldWrite then + Console.WriteLine output + + let day3 (partTwo : bool) (input : string) = + let resultArr, len, lineCount = Day3.parse (input.ToCharArray () |> Array.map byte) +#if DEBUG + let contents = + { + Elements = Array.take len resultArr + Width = len / lineCount + } +#else + use ptr = fixed resultArr + + let contents = + { + Elements = ptr + Length = len + Width = len / lineCount + } +#endif + if not partTwo then + let output = Day3.part1 contents + + if shouldWrite then + Console.WriteLine output + else + let output = Day3.part2 contents + + if shouldWrite then + Console.WriteLine output + + let day4 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day4.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day4.part2 input + + if shouldWrite then + Console.WriteLine output + + let day5 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day5.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day5.part2 input + + if shouldWrite then + Console.WriteLine output + + let day6 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day6.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day6.part2 input + + if shouldWrite then + Console.WriteLine output + + let day7 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day7.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day7.part2 input + + if shouldWrite then + Console.WriteLine output + + let day8 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day8.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day8.part2 input + + if shouldWrite then + Console.WriteLine output + + let day9 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day9.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day9.part2 input + + if shouldWrite then + Console.WriteLine output + + let day10 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day10.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day10.part2 input + + if shouldWrite then + Console.WriteLine output + + let day11 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day11.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day11.part2 input + + if shouldWrite then + Console.WriteLine output + + + let day12 (partTwo : bool) (input : string) = + if not partTwo then + let output = Day12.part1 input + + if shouldWrite then + Console.WriteLine output + else + let output = Day12.part2 input + + if shouldWrite then + Console.WriteLine output + + let allRuns = + [| + day1 + day2 + day3 + day4 + day5 + day6 + day7 + day8 + day9 + day10 + day11 + day12 + |] diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.sln b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.sln index f6ffa4f..612b40d 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.sln +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.sln @@ -6,6 +6,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Test", "Test\Test.fsproj", EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AdventOfCode2023.FSharp.Lib", "AdventOfCode2023.FSharp.Lib\AdventOfCode2023.FSharp.Lib.fsproj", "{95CE0568-3D1A-4060-BB54-52460FB1E399}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AdventOfCode2023.FSharp.Bench", "AdventOfCode2023.FSharp.Bench\AdventOfCode2023.FSharp.Bench.fsproj", "{5FD3221D-2C90-4173-8FC0-90553CEE1D4A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +26,9 @@ Global {95CE0568-3D1A-4060-BB54-52460FB1E399}.Debug|Any CPU.Build.0 = Debug|Any CPU {95CE0568-3D1A-4060-BB54-52460FB1E399}.Release|Any CPU.ActiveCfg = Release|Any CPU {95CE0568-3D1A-4060-BB54-52460FB1E399}.Release|Any CPU.Build.0 = Release|Any CPU + {5FD3221D-2C90-4173-8FC0-90553CEE1D4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FD3221D-2C90-4173-8FC0-90553CEE1D4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FD3221D-2C90-4173-8FC0-90553CEE1D4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FD3221D-2C90-4173-8FC0-90553CEE1D4A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/README.md b/README.md index f900a07..02c41b5 100644 --- a/README.md +++ b/README.md @@ -7,23 +7,109 @@ Ahead-of-time compiled with `PublishAot`, M1 Max. The format is: "answer part1\ntime\nanswer part2\ntime\n...", with possible extra lines indicating how long it took to parse the input if I happen to have split that out. -After day 3: +BenchmarkDotNet: ``` +| Day | IsPartOne | Mean | Error | StdDev | +|---- |---------- |----------:|---------:|---------:| +| 1 | True | 10.23 us | 0.036 us | 0.032 us | +| 1 | False | 17.93 us | 0.203 us | 0.180 us | +| 2 | True | 17.39 us | 0.080 us | 0.075 us | +| 2 | False | 25.42 us | 0.155 us | 0.145 us | +| 3 | True | 65.60 us | 0.393 us | 0.328 us | +| 3 | False | 145.52 us | 0.256 us | 0.200 us | +| 4 | True | 109.78 us | 0.236 us | 0.209 us | +| 4 | False | 110.34 us | 0.081 us | 0.063 us | +| 5 | True | 13.44 us | 0.045 us | 0.042 us | +| 5 | False | 61.70 us | 0.199 us | 0.177 us | + +| Day | IsPartOne | Mean | Error | StdDev | +|---- |---------- |---------------:|------------:|------------:| +| 6 | True | 314.7 ns | 1.87 ns | 1.65 ns | +| 6 | False | 316.3 ns | 0.31 ns | 0.26 ns | +| 7 | True | 89,256.3 ns | 578.24 ns | 540.88 ns | +| 7 | False | 95,062.7 ns | 921.75 ns | 862.21 ns | +| 8 | True | 423,461.0 ns | 7,218.95 ns | 6,752.61 ns | +| 8 | False | 2,045,302.1 ns | 4,338.61 ns | 3,846.06 ns | +| 9 | True | 1,390,976.2 ns | 2,171.39 ns | 1,813.21 ns | +| 9 | False | 2,173,468.1 ns | 3,171.04 ns | 2,647.96 ns | +| 10 | True | 57,460.7 ns | 1,135.45 ns | 2,160.31 ns | +| 10 | False | 694,553.9 ns | 2,935.74 ns | 2,746.09 ns | + +| Day | IsPartOne | Mean | Error | StdDev | Median | +|---- |---------- |----------:|----------:|----------:|----------:| +| 11 | True | 39.085 ms | 0.0355 ms | 0.0297 ms | 39.082 ms | +| 11 | False | 38.608 ms | 0.0270 ms | 0.0211 ms | 38.617 ms | +| 12 | True | 1.846 ms | 0.0044 ms | 0.0041 ms | 1.845 ms | +| 12 | False | 18.692 ms | 0.3676 ms | 0.3775 ms | 18.962 ms | +``` + +After day 12, a single run of the ahead-of-time compiled version: + +``` +=====Day 1===== 54304 -0.549458ms +3.418417ms 54418 -0.710375ms +0.317958ms +=====Day 2===== 2727 -0.119959ms +0.079917ms 56580 -0.155708ms -0.1395ms parse +0.107292ms +=====Day 3===== +0.140292ms parse 540131 -0.1395ms +0.140292ms 86879020 -0.840791ms -4.144166ms total +0.664416ms +=====Day 4===== +27454 +0.390541ms +6857330 +0.360375ms +=====Day 5===== +806029445 +0.161917ms +59370572 +0.249708ms +=====Day 6===== +32076 +0.002917ms +34278221 +0.001667ms +=====Day 7===== +250058342 +0.409792ms +250506580 +0.431167ms +=====Day 8===== +19199 +1.192792ms +13663968099527 +5.276083ms +=====Day 9===== +1898776583 +3.775667ms +1100 +5.365875ms +=====Day 10===== +6842 +0.201208ms +393 +2.226042ms +=====Day 11===== +0.11225ms parse +9947476 +48.423ms +519939907614 +34.836125ms +=====Day 12===== +7402 +4.704375ms +3384337640277 +31.825583ms +151.644334ms total ``` # Building yourself -- 2.51.0