From 9ecf97f7b1794184aff017c56256e4365468fa35 Mon Sep 17 00:00:00 2001 From: filzrev <103790468+filzrev@users.noreply.github.com> Date: Wed, 19 Mar 2025 19:23:31 +0900 Subject: [PATCH] chore: refactor benchmark projects and add benchmark workflow --- .github/workflows/benchmark.yml | 37 +++++ .gitignore | 5 +- .../Benchmark/Benchmarks/IterateBenchmark.cs | 108 +++++++++++++ .../{ReadMe.cs => ReadMeBenchmark.cs} | 0 sandbox/Benchmark/Program.cs | 151 +++--------------- .../Benchmark/Properties/launchSettings.json | 51 ++++++ 6 files changed, 219 insertions(+), 133 deletions(-) create mode 100644 .github/workflows/benchmark.yml create mode 100644 sandbox/Benchmark/Benchmarks/IterateBenchmark.cs rename sandbox/Benchmark/Benchmarks/{ReadMe.cs => ReadMeBenchmark.cs} (100%) create mode 100644 sandbox/Benchmark/Properties/launchSettings.json diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000..e9445080 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,37 @@ +name: Benchmark + +on: + workflow_dispatch: + +jobs: + benchmark: + runs-on: ubuntu-latest + timeout-minutes: 60 # Default: 360 minutes + strategy: + fail-fast: true + steps: + - uses: Cysharp/Actions/.github/actions/checkout@main + - uses: Cysharp/Actions/.github/actions/setup-dotnet@main + - run: dotnet build -c Release + + - name: Run Benchmarks + working-directory: sandbox/Benchmark + run: | + dotnet run -c Release --no-build --no-launch-profile -- --filter "*" --logBuildOutput BenchmarkDotNet.Artifacts --exporters GitHub + + - name: Upload artifacts + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 #v4.6.1 + with: + name: BenchmarkDotNet.Artifacts + path: sandbox/Benchmark/BenchmarkDotNet.Artifacts/ + if-no-files-found: error + + - name: Output results to JobSummary + working-directory: sandbox/Benchmark + shell: pwsh + run: | + $items = Get-ChildItem "BenchmarkDotNet.Artifacts/results/*.md" + foreach($item in $items) { + Write-Output ('## {0}' -f $item.Name) >> $env:GITHUB_STEP_SUMMARY + Write-Output (Get-Content $item.FullName -Raw) >> $env:GITHUB_STEP_SUMMARY + } diff --git a/.gitignore b/.gitignore index 10bef1ae..d83fadf4 100644 --- a/.gitignore +++ b/.gitignore @@ -128,4 +128,7 @@ src/ZLinq.Unity/obj/* src/ZLinq.Unity/Temp/* src/ZLinq.Unity/UserSettings/* src/ZLinq.Unity/*.sln -src/ZLinq.Unity/*.csproj \ No newline at end of file +src/ZLinq.Unity/*.csproj + +# BenchmarkDotNet +BenchmarkDotNet.Artifacts/ diff --git a/sandbox/Benchmark/Benchmarks/IterateBenchmark.cs b/sandbox/Benchmark/Benchmarks/IterateBenchmark.cs new file mode 100644 index 00000000..17e83445 --- /dev/null +++ b/sandbox/Benchmark/Benchmarks/IterateBenchmark.cs @@ -0,0 +1,108 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Order; +using Cathei.LinqGen; +using SpanLinq; +using StructLinq; +using ZLinq; + +namespace Benchmark; + +[ShortRunJob] +[MemoryDiagnoser] +[Orderer(SummaryOrderPolicy.FastestToSlowest)] +public class IterateBenchmark +{ + int[] array = Enumerable.Range(1, 10000).ToArray(); + + public IterateBenchmark() + { + + } + + [Benchmark] + public void SystemLinq() + { + var seq = array + .Select(x => x * 3) + .Where(x => x % 2 == 0); + + foreach (var item in seq) + { + } + } + + [Benchmark] + public void ZLinq() + { + var seq = array.AsValueEnumerable() + .Select(x => x * 3) + .Where(x => x % 2 == 0); + + foreach (var item in seq) { } + } + + //[Benchmark] + //public void ZLinqSpan() + //{ + // var seq = array.AsSpan().AsValueEnumerable() + // .Select, int, int>(x => x * 3) + // .Where, int, int>, int>(x => x % 2 == 0); + + // foreach (var item in seq) + // { + + // } + //} + + [Benchmark] + public void LinqGen() + { + var seq = array.Gen() + .Select(x => x * 3) + .Where(x => x % 2 == 0); + + foreach (var item in seq) + { + + } + } + + [Benchmark] + public void LinqAf() + { + var seq = LinqAF.ArrayExtensionMethods + .Select(array, x => x * 3) + .Where(x => x % 2 == 0); + + foreach (var item in seq) + { + + } + } + + //[Benchmark] + //public void StructLinq() + //{ + // var seq = array.ToValueEnumerable() + // .Select(x => x * 3, x => x) + // .Where(x => x % 2 == 0, x => x); + + // foreach (var item in seq) + // { + + // } + //} + + [Benchmark] + public void SpanLinq() + { + var seq = array.AsSpan() + .Select(x => x * 3) + .Where(x => x % 2 == 0); + + foreach (var item in seq) + { + + } + } +} diff --git a/sandbox/Benchmark/Benchmarks/ReadMe.cs b/sandbox/Benchmark/Benchmarks/ReadMeBenchmark.cs similarity index 100% rename from sandbox/Benchmark/Benchmarks/ReadMe.cs rename to sandbox/Benchmark/Benchmarks/ReadMeBenchmark.cs diff --git a/sandbox/Benchmark/Program.cs b/sandbox/Benchmark/Program.cs index 5f922b23..f07d73fa 100644 --- a/sandbox/Benchmark/Program.cs +++ b/sandbox/Benchmark/Program.cs @@ -1,150 +1,37 @@ -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Order; +using BenchmarkDotNet.Configs; using BenchmarkDotNet.Reports; using BenchmarkDotNet.Running; -using Perfolizer.Horology; using Cathei.LinqGen; +using Perfolizer.Horology; using SpanLinq; -using StructLinq; using ZLinq; -using ZLinq.Linq; -using Benchmark; - -#if !DEBUG - -//BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithTimeUnit(TimeUnit.Millisecond)), args); -//BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithTimeUnit(TimeUnit.Millisecond)), args); -//BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithTimeUnit(TimeUnit.Millisecond)), args); -//BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithTimeUnit(TimeUnit.Millisecond)), args); -// BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithTimeUnit(TimeUnit.Millisecond)), args); - -// BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default), args); -//BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default), args); - -//BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default), args); - - -//BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default), args); - -//BenchmarkRunner.Run(DefaultConfig.Instance, args); -//BenchmarkRunner.Run(DefaultConfig.Instance, args); -//BenchmarkRunner.Run(DefaultConfig.Instance, args); -//BenchmarkRunner.Run(DefaultConfig.Instance, args); -//BenchmarkRunner.Run(DefaultConfig.Instance, args); -BenchmarkRunner.Run(DefaultConfig.Instance, args); -//BenchmarkRunner.Run(DefaultConfig.Instance, args); -#else - -BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithTimeUnit(TimeUnit.Millisecond)), args); - -var i = 0; -foreach (var item in typeof(Enumerable).GetMethods().GroupBy(x => x.Name)) -{ - Console.WriteLine($"- [ ] {item.Key}"); - i++; -} -Console.WriteLine(i); +namespace Benchmark; -#endif -[ShortRunJob] -[MemoryDiagnoser] -[Orderer(SummaryOrderPolicy.FastestToSlowest)] -public class IterateBenchmark +internal static class Program { - int[] array = Enumerable.Range(1, 10000).ToArray(); - - public IterateBenchmark() - { - - } - - [Benchmark] - public void SystemLinq() - { - var seq = array - .Select(x => x * 3) - .Where(x => x % 2 == 0); - - foreach (var item in seq) - { - } - } - - [Benchmark] - public void ZLinq() - { - var seq = array.AsValueEnumerable() - .Select(x => x * 3) - .Where(x => x % 2 == 0); - - foreach (var item in seq) { } - } - - //[Benchmark] - //public void ZLinqSpan() - //{ - // var seq = array.AsSpan().AsValueEnumerable() - // .Select, int, int>(x => x * 3) - // .Where, int, int>, int>(x => x % 2 == 0); - - // foreach (var item in seq) - // { - - // } - //} - - [Benchmark] - public void LinqGen() - { - var seq = array.Gen() - .Select(x => x * 3) - .Where(x => x % 2 == 0); - - foreach (var item in seq) - { - - } - } - - [Benchmark] - public void LinqAf() + public static int Main(string[] args) { - var seq = LinqAF.ArrayExtensionMethods - .Select(array, x => x * 3) - .Where(x => x % 2 == 0); +#if DEBUG + BenchmarkRunner.Run(DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithTimeUnit(TimeUnit.Millisecond)), args); - foreach (var item in seq) + var i = 0; + foreach (var item in typeof(Enumerable).GetMethods().GroupBy(x => x.Name)) { - + Console.WriteLine($"- [ ] {item.Key}"); + i++; } - } - - //[Benchmark] - //public void StructLinq() - //{ - // var seq = array.ToValueEnumerable() - // .Select(x => x * 3, x => x) - // .Where(x => x % 2 == 0, x => x); - - // foreach (var item in seq) - // { - - // } - //} + Console.WriteLine(i); + return 0; +#endif - [Benchmark] - public void SpanLinq() - { - var seq = array.AsSpan() - .Select(x => x * 3) - .Where(x => x % 2 == 0); + if (args != null && args.Length != 0) + Console.WriteLine($"Start ZLinq benchmarks with args: {string.Join(' ', args)}"); - foreach (var item in seq) - { + var switcher = BenchmarkSwitcher.FromAssemblies([typeof(Program).Assembly]); + switcher.Run(args).ToArray(); - } + return 0; } } diff --git a/sandbox/Benchmark/Properties/launchSettings.json b/sandbox/Benchmark/Properties/launchSettings.json new file mode 100644 index 00000000..24732afb --- /dev/null +++ b/sandbox/Benchmark/Properties/launchSettings.json @@ -0,0 +1,51 @@ +{ + "profiles": { + "Default": { + "commandName": "Project", + "commandLineArgs": "--filter Benchmark.IterateBenchmark.*", + + // Available benchmarks: + // "commandLineArgs": "--filter Benchmark.IterateBenchmark.*", + // "commandLineArgs": "--filter Benchmark.LinqPerfBenchmarks.AggregateBy00.*", + // "commandLineArgs": "--filter Benchmark.LinqPerfBenchmarks.Count00.*", + // "commandLineArgs": "--filter Benchmark.LinqPerfBenchmarks.CountBy00.*", + // "commandLineArgs": "--filter Benchmark.LinqPerfBenchmarks.GroupBy00.*", + // "commandLineArgs": "--filter Benchmark.LinqPerfBenchmarks.Order00.*", + // "commandLineArgs": "--filter Benchmark.LinqPerfBenchmarks.Where00.*", + // "commandLineArgs": "--filter Benchmark.LinqPerfBenchmarks.Where01.*", + // "commandLineArgs": "--filter Benchmark.SimdRange.*", + // "commandLineArgs": "--filter Benchmark.SimdSelect.*", + // "commandLineArgs": "--filter Benchmark.LookupBattle.*", + // "commandLineArgs": "--filter Benchmark.LookupBattle.*", + // "commandLineArgs": "--filter Benchmark.ReadMeBenchmark.*", + // "commandLineArgs": "--filter Benchmark.ShuffleBench.*", + // "commandLineArgs": "--filter Benchmark.SimdAny.*", + // "commandLineArgs": "--filter Benchmark.SimdRange.*", + // "commandLineArgs": "--filter Benchmark.SimdSelect.*", + // "commandLineArgs": "--filter Benchmark.SimdSum.*", + // "commandLineArgs": "--filter Benchmark.SimdSumUnsigned.*", + + "workingDirectory": "." + }, + "Select Benchmark": { + "commandName": "Project", + "commandLineArgs": "" + }, + "Run All Benchmarks": { + "commandName": "Project", + "commandLineArgs": "--filter *", + }, + "Run All Benchmarks with --join": { + "commandName": "Project", + "commandLineArgs": "--filter * --join", + }, + "List Benchmark": { + "commandName": "Project", + "commandLineArgs": "--list tree", + }, + "Help": { + "commandName": "Project", + "commandLineArgs": "--help", + } + } +}