From 0b8c56615de26d705f8786b67e8a826b3e44c5db Mon Sep 17 00:00:00 2001 From: Alastair Crabtree Date: Sun, 20 Sep 2020 21:52:20 +0100 Subject: [PATCH] task: change lock count to be 32 based on perf test test-result on 6 (12 HT) core machine: # Locks, Cache req in 10s 1 6240625 2 10452129 6 19198527 12 27735172 24 27086363 32 32524781 128 32039528 1024 31144725 8000 33000461 --- .../CachingServiceMemoryCacheProviderTests.cs | 64 +++++++++++++++++++ LazyCache/CachingService.cs | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/LazyCache.UnitTests/CachingServiceMemoryCacheProviderTests.cs b/LazyCache.UnitTests/CachingServiceMemoryCacheProviderTests.cs index c353199..ae82190 100644 --- a/LazyCache.UnitTests/CachingServiceMemoryCacheProviderTests.cs +++ b/LazyCache.UnitTests/CachingServiceMemoryCacheProviderTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using FluentAssertions; @@ -909,6 +910,69 @@ public async Task GetOrAddAsyncWithImmediateExpirationDoesExpireItems() Assert.That(actual, Is.Null); } + [Test] + [Ignore("Not a real unit tests - just used for hammering the cache")] + public async Task PerfTest() + { + var watch = new Stopwatch(); + watch.Start(); + var asyncThreads = 10; + var syncThreads = 10; + var uniqueCacheItems = 20; + int cacheMiss = 0; + int hits = 0; + var cancel = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + + async Task GetStuffAsync() + { + await Task.Delay(25); + Interlocked.Increment(ref cacheMiss); + return new ComplexTestObject(); + } + + ComplexTestObject GetStuff() + { + Thread.Sleep(25); + Interlocked.Increment(ref cacheMiss); + return new ComplexTestObject(); + } + + + var asyncActions = Task.Run(() => + { + Parallel.For(1, asyncThreads, async i => + { + while (!cancel.IsCancellationRequested) + { + var key = $"stuff-{hits % uniqueCacheItems}"; + var cached = await sut.GetOrAddAsync(key, () => GetStuffAsync(), DateTimeOffset.UtcNow.AddSeconds(1)); + if(!cancel.IsCancellationRequested) Interlocked.Increment(ref hits); + } + }); + }); + + var syncActions = Task.Run(() => + { + Parallel.For(1, syncThreads, i => + { + while (!cancel.IsCancellationRequested) + { + var key = $"stuff-{hits % uniqueCacheItems}"; + var cached = sut.GetOrAdd(key, () => GetStuff(), DateTimeOffset.UtcNow.AddSeconds(1)); + if (!cancel.IsCancellationRequested) Interlocked.Increment(ref hits); + } + }); + }); + + await Task.WhenAll(asyncActions, syncActions); + + watch.Stop(); + Console.WriteLine(watch.Elapsed); + Console.WriteLine("miss " + cacheMiss); + Console.WriteLine("hit " + hits); + } + + [Test] public void GetOrAddWithPolicyAndThenGetObjectReturnsCorrectType() { diff --git a/LazyCache/CachingService.cs b/LazyCache/CachingService.cs index 9107af8..84d5bf8 100644 --- a/LazyCache/CachingService.cs +++ b/LazyCache/CachingService.cs @@ -13,7 +13,7 @@ public class CachingService : IAppCache { private readonly Lazy cacheProvider; - private readonly int[] keyLocks = new int[8192]; + private readonly int[] keyLocks = new int[32]; public CachingService() : this(DefaultCacheProvider) {