From 2ce84c9039a22dfe433a9213e119091fdbed8920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E5=A4=B4?= Date: Sun, 15 Sep 2024 05:06:54 +0800 Subject: [PATCH] =?UTF-8?q?[feat]ICache=E6=96=B0=E5=A2=9E=E5=8D=95key?= =?UTF-8?q?=E7=9A=84Remove=EF=BC=8C=E5=87=8F=E5=B0=91=E6=95=B0=E7=BB=84?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=EF=BC=8C=E9=99=8D=E4=BD=8EGC=E5=8E=8B?= =?UTF-8?q?=E5=8A=9B=EF=BC=8C=E6=8F=90=E5=8D=87=E6=80=A7=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=9C=A8Bench=E5=8E=8B=E6=B5=8B=E4=B8=AD=E6=8F=90=E5=8D=87400?= =?UTF-8?q?=E5=80=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewLife.Core/Caching/Cache.cs | 68 ++++++++++++++++++----------- NewLife.Core/Caching/ICache.cs | 5 +++ NewLife.Core/Caching/MemoryCache.cs | 51 +++++++++++++++------- Test/Program.cs | 11 +++-- 4 files changed, 89 insertions(+), 46 deletions(-) diff --git a/NewLife.Core/Caching/Cache.cs b/NewLife.Core/Caching/Cache.cs index 6b9fae490..ec1e03e2a 100644 --- a/NewLife.Core/Caching/Cache.cs +++ b/NewLife.Core/Caching/Cache.cs @@ -68,6 +68,11 @@ public virtual void Init(String config) { } [return: MaybeNull] public abstract T Get(String key); + /// 移除缓存项 + /// 键 + /// + public abstract Int32 Remove(String key); + /// 批量移除缓存项 /// 键集合 /// @@ -358,7 +363,30 @@ public virtual Int64 Bench(Boolean rand = false, Int32 batch = 0) XTrace.WriteLine($"{Name}性能测试[{(rand ? "随机" : "顺序")}],批大小[{batch}],逻辑处理器 {cpu:n0} 个"); var rs = 0L; - var times = 10_000; + var times = GetTimesPerThread(rand, batch); + + // 提前准备Keys,减少性能测试中的干扰 + var key = "bstr_"; + var key2 = "bint_"; + var max = cpu > 64 ? cpu : 64; + var maxTimes = times * max; + if (!rand) maxTimes = max; + _keys = new String[maxTimes]; + _keys2 = new String[maxTimes]; + + var sb = new StringBuilder(); + for (var i = 0; i < _keys.Length; i++) + { + sb.Clear(); + sb.Append(key); + sb.Append(i); + _keys[i] = sb.ToString(); + + sb.Clear(); + sb.Append(key2); + sb.Append(i); + _keys2[i] = sb.ToString(); + } // 单线程 rs += BenchOne(times, 1, rand, batch); @@ -382,6 +410,14 @@ public virtual Int64 Bench(Boolean rand = false, Int32 batch = 0) return rs; } + /// 获取每个线程测试次数 + /// + /// + /// + protected virtual Int32 GetTimesPerThread(Boolean rand, Int32 batch) => 10_000; + + private String[]? _keys; + private String[]? _keys2; /// 使用指定线程测试指定次数 /// 次数 /// 线程 @@ -392,47 +428,27 @@ public virtual Int64 BenchOne(Int64 times, Int32 threads, Boolean rand, Int32 ba if (threads <= 0) threads = Environment.ProcessorCount; if (times <= 0) times = threads * 1_000; - //XTrace.WriteLine(""); XTrace.WriteLine($"测试 {times:n0} 项,{threads,3:n0} 线程"); var rs = 3L; //提前执行一次网络操作,预热链路 - var key = "bstr_"; + var key = _keys![0]; Set(key, Rand.NextString(32)); _ = Get(key); Remove(key); - var key2 = "bint_"; - var keys = new String[times]; - var keys2 = new String[times]; - var sb = new StringBuilder(); - for (var i = 0; i < times; i++) - { - //keys[i] = key + i; - //keys2[i] = key2 + i; - sb.Clear(); - sb.Append(key); - sb.Append(i); - keys[i] = sb.ToString(); - - sb.Clear(); - sb.Append(key2); - sb.Append(i); - keys2[i] = sb.ToString(); - } - // 赋值测试 - rs += BenchSet(keys, times, threads, rand, batch); + rs += BenchSet(_keys, times, threads, rand, batch); // 读取测试 - rs += BenchGet(keys, times, threads, rand, batch); + rs += BenchGet(_keys, times, threads, rand, batch); // 删除测试 - rs += BenchRemove(keys, times, threads, rand, batch); + rs += BenchRemove(_keys, times, threads, rand, batch); // 累加测试 - rs += BenchInc(keys2, times, threads, rand, batch); + rs += BenchInc(_keys2!, times, threads, rand, batch); return rs; } diff --git a/NewLife.Core/Caching/ICache.cs b/NewLife.Core/Caching/ICache.cs index f33d74efe..868a0fc7c 100644 --- a/NewLife.Core/Caching/ICache.cs +++ b/NewLife.Core/Caching/ICache.cs @@ -53,6 +53,11 @@ public interface ICache [return: MaybeNull] T Get(String key); + /// 移除缓存项 + /// 键 + /// + Int32 Remove(String key); + /// 批量移除缓存项 /// 键集合 /// diff --git a/NewLife.Core/Caching/MemoryCache.cs b/NewLife.Core/Caching/MemoryCache.cs index f42a0be70..3973ac016 100644 --- a/NewLife.Core/Caching/MemoryCache.cs +++ b/NewLife.Core/Caching/MemoryCache.cs @@ -165,10 +165,28 @@ public override T Get(String key) var rs = item.Visit(); if (rs == null) return default; + if (rs is T t) return t; return rs.ChangeType(); } + /// 移除缓存项 + /// 键 + /// 实际移除个数 + public override Int32 Remove(String key) + { + var count = 0; + + if (_cache.TryRemove(key, out _)) + { + count++; + + Interlocked.Decrement(ref _count); + } + + return count; + } + /// 批量移除缓存项 /// 键集合 /// 实际移除个数 @@ -522,8 +540,8 @@ public Int64 Inc(Int64 value) Object oldValue; do { - oldValue = _Value ?? 0; - newValue = oldValue.ToLong() + value.ToLong(); + oldValue = _Value ?? 0L; + newValue = (oldValue is Int64 n ? n : oldValue.ToLong()) + value; } while (Interlocked.CompareExchange(ref _Value, newValue, oldValue) != oldValue); Visit(); @@ -541,8 +559,8 @@ public Double Inc(Double value) Object oldValue; do { - oldValue = _Value ?? 0; - newValue = oldValue.ToDouble() + value.ToDouble(); + oldValue = _Value ?? 0d; + newValue = (oldValue is Double n ? n : oldValue.ToDouble()) + value; } while (Interlocked.CompareExchange(ref _Value, newValue, oldValue) != oldValue); Visit(); @@ -560,8 +578,8 @@ public Int64 Dec(Int64 value) Object oldValue; do { - oldValue = _Value ?? 0; - newValue = oldValue.ToLong() - value.ToLong(); + oldValue = _Value ?? 0L; + newValue = (oldValue is Int64 n ? n : oldValue.ToLong()) - value; } while (Interlocked.CompareExchange(ref _Value, newValue, oldValue) != oldValue); Visit(); @@ -579,8 +597,8 @@ public Double Dec(Double value) Object oldValue; do { - oldValue = _Value ?? 0; - newValue = oldValue.ToDouble() - value.ToDouble(); + oldValue = _Value ?? 0d; + newValue = (oldValue is Double n ? n : oldValue.ToDouble()) - value; } while (Interlocked.CompareExchange(ref _Value, newValue, oldValue) != oldValue); Visit(); @@ -807,19 +825,20 @@ public void Load(Stream stream) #endregion #region 性能测试 - /// 使用指定线程测试指定次数 - /// 次数 - /// 线程 - /// 随机读写 - /// 批量操作 - public override Int64 BenchOne(Int64 times, Int32 threads, Boolean rand, Int32 batch) + /// 获取每个线程测试次数 + /// + /// + /// + protected override Int32 GetTimesPerThread(Boolean rand, Int32 batch) { + var times = base.GetTimesPerThread(rand, batch); + if (rand) times *= 100; else - times *= 1000; + times *= 10000; - return base.BenchOne(times, threads, rand, batch); + return times; } #endregion } diff --git a/Test/Program.cs b/Test/Program.cs index 4f6e1cba0..23066063e 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -77,7 +77,7 @@ private static async Task Main(String[] args) try { #endif - Test1(); + Test4(); #if !DEBUG } catch (Exception ex) @@ -239,9 +239,12 @@ private static void Test4() if (Console.ReadKey().KeyChar != '1') mode = true; var batch = 0; - Console.WriteLine(); - Console.Write("选择输入批大小[0]:"); - batch = Console.ReadLine().ToInt(); + if (mode) + { + Console.WriteLine(); + Console.Write("选择输入批大小[0]:"); + batch = Console.ReadLine().ToInt(); + } Console.Clear();