diff --git a/BitFaster.Caching.Benchmarks/Lfu/CmSketchFlat.cs b/BitFaster.Caching.Benchmarks/Lfu/CmSketchFlat.cs index b70ec3af..fee80984 100644 --- a/BitFaster.Caching.Benchmarks/Lfu/CmSketchFlat.cs +++ b/BitFaster.Caching.Benchmarks/Lfu/CmSketchFlat.cs @@ -199,7 +199,7 @@ private int IndexOf(int item, int i) return ((int)hash) & tableMask; } - private int Spread(int x) + private static int Spread(int x) { uint y = (uint)x; y = ((y >> 16) ^ y) * 0x45d9f3b; diff --git a/BitFaster.Caching.Benchmarks/LockBench.cs b/BitFaster.Caching.Benchmarks/LockBench.cs new file mode 100644 index 00000000..c8ef40a8 --- /dev/null +++ b/BitFaster.Caching.Benchmarks/LockBench.cs @@ -0,0 +1,60 @@ +using System.Threading; +using Benchly; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; + +namespace BitFaster.Caching.Benchmarks +{ + [SimpleJob(RuntimeMoniker.Net90)] + [MemoryDiagnoser(displayGenColumns: false)] + [HideColumns("Job", "Median", "RatioSD", "Alloc Ratio")] + [ColumnChart(Title = "Try enter ({JOB})")] + public class LockBench + { + private int _value; + private readonly object monitorLock = new object(); +#if NET9_0_OR_GREATER + private readonly Lock threadingLock = new Lock(); +#endif + + [Benchmark(Baseline = true)] + public void UseMonitor() + { + bool lockTaken = false; + Monitor.TryEnter(monitorLock, ref lockTaken); + + if (lockTaken) + { + try + { + _value++; + } + finally + { + if (lockTaken) + { + Monitor.Exit(monitorLock); + } + } + } + } + + [Benchmark()] + public void UseLock() + { +#if NET9_0_OR_GREATER + if (threadingLock.TryEnter()) + { + try + { + _value++; + } + finally + { + threadingLock.Exit(); + } + } +#endif + } + } +} diff --git a/BitFaster.Caching.UnitTests/Lru/TLruTickCount64PolicyTests .cs b/BitFaster.Caching.UnitTests/Lru/TLruTickCount64PolicyTests.cs similarity index 100% rename from BitFaster.Caching.UnitTests/Lru/TLruTickCount64PolicyTests .cs rename to BitFaster.Caching.UnitTests/Lru/TLruTickCount64PolicyTests.cs diff --git a/BitFaster.Caching/Atomic/AtomicEx.cs b/BitFaster.Caching/Atomic/AtomicEx.cs index 0ead94be..1e600ab1 100644 --- a/BitFaster.Caching/Atomic/AtomicEx.cs +++ b/BitFaster.Caching/Atomic/AtomicEx.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Text; namespace BitFaster.Caching.Atomic { @@ -21,6 +20,7 @@ internal static int EnumerateCount(IEnumerator enumerator) internal static ICollection FilterKeys(IEnumerable> kvps, Func filter) { +#pragma warning disable CA1851 // Here we will double enumerate the kvps list. Alternative is to lazy init the size which will keep resizing // the List, and spam allocs if the list is long. List keys = new List(kvps.Count()); @@ -34,6 +34,7 @@ internal static ICollection FilterKeys(IEnumerable> } return new ReadOnlyCollection(keys); +#pragma warning restore CA1851 } } } diff --git a/BitFaster.Caching/Lru/ConcurrentLru.cs b/BitFaster.Caching/Lru/ConcurrentLru.cs index bd7192a6..36376a51 100644 --- a/BitFaster.Caching/Lru/ConcurrentLru.cs +++ b/BitFaster.Caching/Lru/ConcurrentLru.cs @@ -40,13 +40,13 @@ internal static ICache Create(LruInfo info) }; } - private static ICache CreateExpireAfterAccess(LruInfo info) where K : notnull where TP : struct, ITelemetryPolicy + private static ConcurrentLruCore, AfterAccessPolicy, TP> CreateExpireAfterAccess(LruInfo info) where K : notnull where TP : struct, ITelemetryPolicy { return new ConcurrentLruCore, AfterAccessPolicy, TP>( info.ConcurrencyLevel, info.Capacity, info.KeyComparer, new AfterAccessPolicy(info.TimeToExpireAfterAccess!.Value), default); } - private static ICache CreateExpireAfter(LruInfo info, IExpiryCalculator expiry) where K : notnull where TP : struct, ITelemetryPolicy + private static ConcurrentLruCore, DiscretePolicy, TP> CreateExpireAfter(LruInfo info, IExpiryCalculator expiry) where K : notnull where TP : struct, ITelemetryPolicy { return new ConcurrentLruCore, DiscretePolicy, TP>( info.ConcurrencyLevel, info.Capacity, info.KeyComparer, new DiscretePolicy(expiry), default);