From 89717c5708b02f13a89f243ed50da8a5f6704df3 Mon Sep 17 00:00:00 2001
From: Measurity <measuring.infinity@gmail.com>
Date: Mon, 21 Aug 2023 16:15:52 +0200
Subject: [PATCH] Added Unity mono benchmark

---
 .../BinaryPack.Benchmark.csproj               |  2 +-
 .../Implementation/Benchmark.cs               |  2 +
 .../Jobs/UnityJobAttribute.cs                 | 56 +++++++++++++++++++
 samples/BinaryPack.Benchmark/Program.cs       | 18 ++----
 4 files changed, 65 insertions(+), 13 deletions(-)
 create mode 100644 samples/BinaryPack.Benchmark/Jobs/UnityJobAttribute.cs

diff --git a/samples/BinaryPack.Benchmark/BinaryPack.Benchmark.csproj b/samples/BinaryPack.Benchmark/BinaryPack.Benchmark.csproj
index 9e4d279..83aad09 100644
--- a/samples/BinaryPack.Benchmark/BinaryPack.Benchmark.csproj
+++ b/samples/BinaryPack.Benchmark/BinaryPack.Benchmark.csproj
@@ -9,7 +9,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
+    <PackageReference Include="BenchmarkDotNet" Version="0.13.7" />
     <PackageReference Include="BinaryPack" Version="1.0.3" Condition="'$(TargetFramework)' == 'net7'" />
     <PackageReference Include="IsExternalInit" Version="1.0.3" Condition="'$(TargetFramework)' == 'net472'" />
     <PackageReference Include="MessagePack" Version="2.3.85" />
diff --git a/samples/BinaryPack.Benchmark/Implementation/Benchmark.cs b/samples/BinaryPack.Benchmark/Implementation/Benchmark.cs
index 7e4f497..fe3eb22 100644
--- a/samples/BinaryPack.Benchmark/Implementation/Benchmark.cs
+++ b/samples/BinaryPack.Benchmark/Implementation/Benchmark.cs
@@ -4,6 +4,7 @@
 using BenchmarkDotNet.Configs;
 using BenchmarkDotNet.Exporters.Csv;
 using BenchmarkDotNet.Jobs;
+using BinaryPack.Benchmark.Jobs;
 using BinaryPack.Models.Interfaces;
 using JsonTextWriter = Newtonsoft.Json.JsonTextWriter;
 using JsonTextReader = Newtonsoft.Json.JsonTextReader;
@@ -20,6 +21,7 @@ namespace BinaryPack.Benchmark.Implementation
     [MemoryDiagnoser]
     [SimpleJob(RuntimeMoniker.Net472, id: "NET_472")]
     [SimpleJob(RuntimeMoniker.Net70, id:"NET_7")]
+    [UnityJob("2019.4.36f1")]
     [CategoriesColumn]
     [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
     public partial class Benchmark<T> where T : class, IInitializable, IEquatable<T>, new()
diff --git a/samples/BinaryPack.Benchmark/Jobs/UnityJobAttribute.cs b/samples/BinaryPack.Benchmark/Jobs/UnityJobAttribute.cs
new file mode 100644
index 0000000..4ccf592
--- /dev/null
+++ b/samples/BinaryPack.Benchmark/Jobs/UnityJobAttribute.cs
@@ -0,0 +1,56 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Loggers;
+using Microsoft.Win32;
+
+namespace BinaryPack.Benchmark.Jobs;
+
+[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true)]
+public class UnityJobAttribute : MonoJobAttribute
+{
+    public UnityJobAttribute(string version)
+        : base($"Unity {version}", GetUnityMonoExeFromVersion(version))
+    {
+    }
+
+    private static string GetUnityMonoExeFromVersion(string version)
+    {
+        static void LogUnityNotOnMachine(string version)
+        {
+            ConsoleLogger.Default.WriteLineError($"Unity {version} was not found on this machine.");
+        }
+
+        // TODO: Support job on Mac/Linux platforms.
+        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+        {
+            ConsoleLogger.Default.WriteLineError("Unity jobs are not yet supported on operating systems other than Windows.");
+            return "";
+        }
+        string? unityPath;
+        using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64))
+        using (RegistryKey? unityInstaller = baseKey.OpenSubKey($@"SOFTWARE\Unity Technologies\Installer\Unity {version}"))
+        {
+            if (unityInstaller == null)
+            {
+                LogUnityNotOnMachine(version);
+                return "";
+            }
+            unityPath = unityInstaller.GetValue("Location x64")?.ToString();
+            if (unityPath == null)
+            {
+                LogUnityNotOnMachine(version);
+                return "";
+            }
+        }
+        string unityMonoExe = @$"{unityPath}\Editor\Data\MonoBleedingEdge\bin\mono.exe";
+        if (!File.Exists(unityMonoExe))
+        {
+            LogUnityNotOnMachine(version);
+            return "";
+        }
+
+        return unityMonoExe;
+    }
+}
diff --git a/samples/BinaryPack.Benchmark/Program.cs b/samples/BinaryPack.Benchmark/Program.cs
index 2adcb2c..56df035 100644
--- a/samples/BinaryPack.Benchmark/Program.cs
+++ b/samples/BinaryPack.Benchmark/Program.cs
@@ -2,19 +2,13 @@
 using BinaryPack.Benchmark.Implementation;
 using BinaryPack.Models;
 
-namespace BinaryPack.Benchmark
+namespace BinaryPack.Benchmark;
+
+public class Program
 {
-    public class Program
+    public static void Main()
     {
-        public static void Main()
-        {
-            /* =================
-             * BenchmarkDotNet
-             * ================
-             * In order to run this benchmark, compile this project in Release mode,
-             * then go to its bin\Release\net* folder, open a cmd prompt
-             * and type "dotnet BinaryPack.Benchmark.dll */
-            BenchmarkRunner.Run<Benchmark<JsonResponseModel>>();
-        }
+        // Run via CLI: dotnet run --project BinaryPack.Benchmark.csproj -c Release --framework net472
+        BenchmarkRunner.Run<Benchmark<JsonResponseModel>>();
     }
 }