From 9092c40417b28dca1e7ee8a37d299b4e15c2524a Mon Sep 17 00:00:00 2001 From: prozolic <42107886+prozolic@users.noreply.github.com> Date: Wed, 30 Apr 2025 14:41:55 +0900 Subject: [PATCH 1/2] Improve LongCount(predicate) from array performance --- .../AllAnyPredicateWithCapturedLambda.cs | 31 +++++++++++++++ src/ZLinq/Linq/LongCount.cs | 39 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/sandbox/Benchmark/Benchmarks/AllAnyPredicateWithCapturedLambda.cs b/sandbox/Benchmark/Benchmarks/AllAnyPredicateWithCapturedLambda.cs index a3743752..2beb31f9 100644 --- a/sandbox/Benchmark/Benchmarks/AllAnyPredicateWithCapturedLambda.cs +++ b/sandbox/Benchmark/Benchmarks/AllAnyPredicateWithCapturedLambda.cs @@ -110,3 +110,34 @@ public int Linq() return _nums.Count(i => i <= _target); } } + +[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] +public class LongCountPredicateWithCapturedLambda +{ + [Params(10, 100, 1000, 10000)] + public int N; + + int[] _nums = default!; + int _target; + + [GlobalSetup] + public void Setup() + { + _nums = Enumerable.Range(1, N).ToArray(); + _target = N; + } + + [Benchmark] + [BenchmarkCategory(Categories.ZLinq)] + public long ZLinq() + { + return _nums.AsValueEnumerable().LongCount(i => i <= _target); + } + + [Benchmark] + [BenchmarkCategory(Categories.LINQ)] + public long Linq() + { + return _nums.LongCount(i => i <= _target); + } +} diff --git a/src/ZLinq/Linq/LongCount.cs b/src/ZLinq/Linq/LongCount.cs index 3febbba6..b00c1e88 100644 --- a/src/ZLinq/Linq/LongCount.cs +++ b/src/ZLinq/Linq/LongCount.cs @@ -60,5 +60,44 @@ public static Int64 LongCount(this ValueEnumerable(this ValueEnumerable, TSource> source, Func predicate) + { + ArgumentNullException.ThrowIfNull(predicate); + + var array = source.Enumerator.GetSource(); + if (array.GetType() != typeof(TSource[])) + { + return LongCount(array, predicate); + } + + var longcount = 0; + + var span = (ReadOnlySpan)array; + for (int i = 0; i < span.Length; i++) + { + if (predicate(span[i])) + { + longcount++; + } + } + + return longcount; + + [MethodImpl(MethodImplOptions.NoInlining)] + static Int64 LongCount(TSource[] array, Func predicate) + { + var longCount = 0; + for (int i = 0; i < array.Length; i++) + { + if (predicate(array[i])) + { + longCount++; + } + } + return longCount; + } + } + } } From bc38aae1d412f2afe6b8526d0c90df8e688d68cd Mon Sep 17 00:00:00 2001 From: prozolic <42107886+prozolic@users.noreply.github.com> Date: Wed, 30 Apr 2025 14:51:06 +0900 Subject: [PATCH 2/2] Fix variable naming --- src/ZLinq/Linq/LongCount.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ZLinq/Linq/LongCount.cs b/src/ZLinq/Linq/LongCount.cs index b00c1e88..560313a9 100644 --- a/src/ZLinq/Linq/LongCount.cs +++ b/src/ZLinq/Linq/LongCount.cs @@ -71,18 +71,18 @@ public static Int64 LongCount(this ValueEnumerable, return LongCount(array, predicate); } - var longcount = 0; + var longCount = 0; var span = (ReadOnlySpan)array; for (int i = 0; i < span.Length; i++) { if (predicate(span[i])) { - longcount++; + longCount++; } } - return longcount; + return longCount; [MethodImpl(MethodImplOptions.NoInlining)] static Int64 LongCount(TSource[] array, Func predicate)