Bench
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Run.fs" />
|
||||||
|
<Compile Include="Inputs.fs" />
|
||||||
|
<Compile Include="Program.fs"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AdventOfCode2023.FSharp.Lib\AdventOfCode2023.FSharp.Lib.fsproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@@ -0,0 +1,19 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
open System.IO
|
||||||
|
open System.Reflection
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
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]
|
@@ -0,0 +1,70 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
open BenchmarkDotNet.Attributes
|
||||||
|
open BenchmarkDotNet.Configs
|
||||||
|
open BenchmarkDotNet.Running
|
||||||
|
|
||||||
|
module Benchmarks =
|
||||||
|
type Benchmark1To5 () =
|
||||||
|
[<GlobalSetup>]
|
||||||
|
member _.Setup () = Run.shouldWrite <- false
|
||||||
|
|
||||||
|
[<Params(1, 2, 3, 4, 5)>]
|
||||||
|
member val Day = 0 with get, set
|
||||||
|
|
||||||
|
[<Params(false, true)>]
|
||||||
|
member val IsPartOne = false with get, set
|
||||||
|
|
||||||
|
[<Benchmark>]
|
||||||
|
member this.Benchmark () : unit =
|
||||||
|
Run.allRuns.[this.Day - 1] (not this.IsPartOne) (Inputs.day this.Day)
|
||||||
|
|
||||||
|
[<GlobalCleanup>]
|
||||||
|
member _.Cleanup () = Run.shouldWrite <- true
|
||||||
|
|
||||||
|
|
||||||
|
type Benchmark6To10 () =
|
||||||
|
[<GlobalSetup>]
|
||||||
|
member _.Setup () = Run.shouldWrite <- false
|
||||||
|
|
||||||
|
[<Params(6, 7, 8, 9, 10)>]
|
||||||
|
member val Day = 0 with get, set
|
||||||
|
|
||||||
|
[<Params(false, true)>]
|
||||||
|
member val IsPartOne = false with get, set
|
||||||
|
|
||||||
|
[<Benchmark>]
|
||||||
|
member this.Benchmark () : unit =
|
||||||
|
Run.allRuns.[this.Day - 1] (not this.IsPartOne) (Inputs.day this.Day)
|
||||||
|
|
||||||
|
[<GlobalCleanup>]
|
||||||
|
member _.Cleanup () = Run.shouldWrite <- true
|
||||||
|
|
||||||
|
type Benchmark11To15 () =
|
||||||
|
[<GlobalSetup>]
|
||||||
|
member _.Setup () = Run.shouldWrite <- false
|
||||||
|
|
||||||
|
[<Params(11, 12)>]
|
||||||
|
member val Day = 0 with get, set
|
||||||
|
|
||||||
|
[<Params(false, true)>]
|
||||||
|
member val IsPartOne = false with get, set
|
||||||
|
|
||||||
|
[<Benchmark>]
|
||||||
|
member this.Benchmark () : unit =
|
||||||
|
Run.allRuns.[this.Day - 1] (not this.IsPartOne) (Inputs.day this.Day)
|
||||||
|
|
||||||
|
[<GlobalCleanup>]
|
||||||
|
member _.Cleanup () = Run.shouldWrite <- true
|
||||||
|
|
||||||
|
module Program =
|
||||||
|
|
||||||
|
[<EntryPoint>]
|
||||||
|
let main args =
|
||||||
|
let config =
|
||||||
|
ManualConfig.Create(DefaultConfig.Instance).WithOptions ConfigOptions.DisableOptimizationsValidator
|
||||||
|
|
||||||
|
let _summary = BenchmarkRunner.Run<Benchmarks.Benchmark1To5> config
|
||||||
|
let _summary = BenchmarkRunner.Run<Benchmarks.Benchmark6To10> config
|
||||||
|
let _summary = BenchmarkRunner.Run<Benchmarks.Benchmark11To15> config
|
||||||
|
0
|
190
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Run.fs
Normal file
190
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Bench/Run.fs
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#else
|
||||||
|
#nowarn "9"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
open System
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
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
|
||||||
|
|]
|
@@ -6,6 +6,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Test", "Test\Test.fsproj",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AdventOfCode2023.FSharp.Lib", "AdventOfCode2023.FSharp.Lib\AdventOfCode2023.FSharp.Lib.fsproj", "{95CE0568-3D1A-4060-BB54-52460FB1E399}"
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AdventOfCode2023.FSharp.Lib", "AdventOfCode2023.FSharp.Lib\AdventOfCode2023.FSharp.Lib.fsproj", "{95CE0568-3D1A-4060-BB54-52460FB1E399}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AdventOfCode2023.FSharp.Bench", "AdventOfCode2023.FSharp.Bench\AdventOfCode2023.FSharp.Bench.fsproj", "{5FD3221D-2C90-4173-8FC0-90553CEE1D4A}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{95CE0568-3D1A-4060-BB54-52460FB1E399}.Release|Any CPU.Build.0 = 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
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
104
README.md
104
README.md
@@ -7,23 +7,109 @@
|
|||||||
Ahead-of-time compiled with `PublishAot`, M1 Max.
|
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.
|
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
|
54304
|
||||||
0.549458ms
|
3.418417ms
|
||||||
54418
|
54418
|
||||||
0.710375ms
|
0.317958ms
|
||||||
|
=====Day 2=====
|
||||||
2727
|
2727
|
||||||
0.119959ms
|
0.079917ms
|
||||||
56580
|
56580
|
||||||
0.155708ms
|
0.107292ms
|
||||||
0.1395ms parse
|
=====Day 3=====
|
||||||
|
0.140292ms parse
|
||||||
540131
|
540131
|
||||||
0.1395ms
|
0.140292ms
|
||||||
86879020
|
86879020
|
||||||
0.840791ms
|
0.664416ms
|
||||||
4.144166ms total
|
=====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
|
# Building yourself
|
||||||
|
Reference in New Issue
Block a user