From 46de95275ec34a61d18cbde7368076b1e712949e Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 30 Oct 2025 05:07:27 +0100 Subject: [PATCH 1/3] Initial commit with task details for issue #96 Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: undefined --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..871d979 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: undefined +Your prepared branch: issue-96-b6a6427e +Your prepared working directory: /tmp/gh-issue-solver-1761797244778 + +Proceed. \ No newline at end of file From 70c55b3839c7f4dfa684502166f6f246dbaa2438 Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 30 Oct 2025 05:11:24 +0100 Subject: [PATCH 2/3] Add benchmarks for [[likely]]/[[unlikely]] attribute performance testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements comprehensive benchmarks comparing different optimization strategies in C# that simulate C++ [[likely]]/[[unlikely]] branch prediction hints: - AggressiveInlining: Forces method inlining for hot paths - AggressiveOptimization: Enables aggressive optimizations - DoesNotReturn attribute: Helps optimizer understand exception paths - Code organization: Hot path first vs exception path first - Generic version: Tests modern .NET generic math optimizations These benchmarks help evaluate performance impact of different approaches to branch prediction optimization in C#, addressing issue #96. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../MathBenchmarks.cs | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/csharp/Platform.Numbers.Benchmarks/MathBenchmarks.cs b/csharp/Platform.Numbers.Benchmarks/MathBenchmarks.cs index 77a4dbd..2339878 100644 --- a/csharp/Platform.Numbers.Benchmarks/MathBenchmarks.cs +++ b/csharp/Platform.Numbers.Benchmarks/MathBenchmarks.cs @@ -1,4 +1,8 @@ using BenchmarkDotNet.Attributes; +using System; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Runtime.CompilerServices; namespace Platform.Numbers.Benchmarks { @@ -191,6 +195,95 @@ public static ulong FactorialWhileLoopWithoutArrayAndCountingArrayLength(ulong n } return r; } + + // Simulating [[likely]] - Hot path optimization with AggressiveInlining + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong FactorialWithAggressiveInlining(ulong n) + { + // Likely path: n is within bounds (hot path first) + if (n <= 20) + { + return _factorials[n]; + } + // Unlikely path: out of range + ThrowOutOfRange(); + return 0; // Never reached + } + + // Simulating [[likely]] with AggressiveOptimization + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + public static ulong FactorialWithAggressiveOptimization(ulong n) + { + // Likely path: n is within bounds + if (n <= 20) + { + return _factorials[n]; + } + // Unlikely path: out of range + ThrowOutOfRange(); + return 0; // Never reached + } + + // Simulating [[likely]] with both AggressiveInlining and AggressiveOptimization + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static ulong FactorialWithBothOptimizations(ulong n) + { + // Likely path: n is within bounds + if (n <= 20) + { + return _factorials[n]; + } + // Unlikely path: out of range + ThrowOutOfRange(); + return 0; // Never reached + } + + // Helper method marked as DoesNotReturn to help optimizer understand exception path + [DoesNotReturn] + [MethodImpl(MethodImplOptions.NoInlining)] + private static void ThrowOutOfRange() + { + throw new ArgumentOutOfRangeException("n", "Only numbers from 0 to 20 are supported by unsigned integer with 64 bits length."); + } + + // Alternative: Exception in the same method (no DoesNotReturn separation) + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static ulong FactorialWithInlineException(ulong n) + { + if (n <= 20) + { + return _factorials[n]; + } + throw new ArgumentOutOfRangeException("n", "Only numbers from 0 to 20 are supported by unsigned integer with 64 bits length."); + } + + // Reverse order: unlikely path first (anti-pattern, for comparison) + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + public static ulong FactorialUnlikelyFirst(ulong n) + { + // Unlikely path first + if (n > 20) + { + ThrowOutOfRange(); + } + // Likely path + return _factorials[n]; + } + + // Generic version simulating [[likely]] for modern .NET + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static TNumber FactorialGenericOptimized(TNumber n) + where TNumber : IUnsignedNumber, IComparisonOperators + { + // Likely path: n is within bounds + if (n >= TNumber.Zero && n <= TNumber.CreateTruncating(20)) + { + return TNumber.CreateTruncating(_factorials[ulong.CreateTruncating(n)]); + } + // Unlikely path: out of range + ThrowOutOfRange(); + return TNumber.Zero; // Never reached + } } private const ulong FactorialNumber = 19; @@ -247,5 +340,42 @@ public ulong FactorialWhileWithoutArrayAndCountingArrayLength() { return Alternatives.FactorialWhileLoopWithoutArrayAndCountingArrayLength(FactorialNumber); } + + // Benchmarks for [[likely]]/[[unlikely]] simulation + [Benchmark] + public ulong FactorialWithAggressiveInlining() + { + return Alternatives.FactorialWithAggressiveInlining(FactorialNumber); + } + + [Benchmark] + public ulong FactorialWithAggressiveOptimization() + { + return Alternatives.FactorialWithAggressiveOptimization(FactorialNumber); + } + + [Benchmark] + public ulong FactorialWithBothOptimizations() + { + return Alternatives.FactorialWithBothOptimizations(FactorialNumber); + } + + [Benchmark] + public ulong FactorialWithInlineException() + { + return Alternatives.FactorialWithInlineException(FactorialNumber); + } + + [Benchmark] + public ulong FactorialUnlikelyFirst() + { + return Alternatives.FactorialUnlikelyFirst(FactorialNumber); + } + + [Benchmark] + public ulong FactorialGenericOptimized() + { + return Alternatives.FactorialGenericOptimized(FactorialNumber); + } } } From 437711ef53e940a388dab13b1d92998c75b91bc9 Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 30 Oct 2025 05:12:59 +0100 Subject: [PATCH 3/3] Revert "Initial commit with task details for issue #96" This reverts commit 46de95275ec34a61d18cbde7368076b1e712949e. --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 871d979..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: undefined -Your prepared branch: issue-96-b6a6427e -Your prepared working directory: /tmp/gh-issue-solver-1761797244778 - -Proceed. \ No newline at end of file