本文使用 benchmarkdotnet 測試字典的性能,在使用字典獲取一個可能存在的值的時候可以使用兩個不同的寫法,於是本文分析兩個寫法的性能。
判斷值存在,如果值存在就獲取值,可以使用下面兩個不同的方法
一個方法是使用 TryGetValue 請看下面代碼
if (Dictionary.TryGetValue(xx, out var foo)) { }
另一個方法是先判斷是否存在然後再獲取,請看下面代碼
if(Dictionary.ContainsKey(xx)) { var foo = Dictionary[xx]; }
於是本文就使用benchmarkdotnet 測試兩個方法的性能
下面是進行測試的數據,測試的代碼放在本文的最後。這裏的 TryGetExist 方法就是嘗試獲取一個值,這個值是存在的。而 ContainGetExist 是先判斷值是否存在,如果存在就嘗試獲取這個值。
BenchmarkDotNet=v0.10.14, OS=Windows 10.0.17134 Intel Core i7-6700 CPU 3.40GHz (Skylake), 1 CPU, 8 logical and 4 physical cores Frequency=3328130 Hz, Resolution=300.4690 ns, Timer=TSC [Host] : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3132.0 [AttachedDebugger] DefaultJob : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3132.0
Method | Mean | Error | StdDev | Median |
---|---|---|---|---|
TryGetExist | 30.26 ns | 0.6057 ns | 0.5949 ns | 30.11 ns |
ContainGetExist | 46.36 ns | 1.0883 ns | 3.1919 ns | 44.90 ns |
TryGetNoExist | 20.23 ns | 0.4661 ns | 0.7658 ns | 19.93 ns |
ContainGetNoExist | 18.68 ns | 0.2569 ns | 0.2403 ns | 18.66 ns |
同樣對比 ConcurrentDictionary 線程安全的類的性能,也就是將會上面的 Foo 測試類的字典替換爲 ConcurrentDictionary 其他代碼都不修改,下面是測試的數據,可以看到使用 TryGetValue 的性能依然比較好
BenchmarkDotNet=v0.10.14, OS=Windows 10.0.17134 Intel Core i7-6700 CPU 3.40GHz (Skylake), 1 CPU, 8 logical and 4 physical cores Frequency=3328130 Hz, Resolution=300.4690 ns, Timer=TSC [Host] : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3132.0 [AttachedDebugger] DefaultJob : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3132.0
Method | Mean | Error | StdDev | Median |
---|---|---|---|---|
TryGetExist | 31.20 ns | 0.4644 ns | 0.3625 ns | 31.17 ns |
ContainGetExist | 66.80 ns | 2.4692 ns | 7.2806 ns | 63.84 ns |
TryGetNoExist | 20.07 ns | 0.1254 ns | 0.1112 ns | 20.04 ns |
ContainGetNoExist | 27.63 ns | 0.4230 ns | 0.3956 ns | 27.65 ns |
所有代碼
public class Foo { /// <inheritdoc /> public Foo() { var ran = new Random(); bool set = false; for (int i = 0; i < 100000; i++) { LazyDictionary[ran.Next().ToString() + "-" + i.ToString()] = ran.Next().ToString(); if (!set) { if (ran.Next() < i) { set = true; LazyDictionary["lindexi"] = "逗比"; } } } } [Benchmark] public void TryGetExist() { if (LazyDictionary.TryGetValue("lindexi", out var foo)) { _foo = foo; } } [Benchmark] public void ContainGetExist() { if (LazyDictionary.ContainsKey("lindexi")) { _foo = LazyDictionary["lindexi"]; } } [Benchmark] public void TryGetNoExist() { if (LazyDictionary.TryGetValue("lindexi123", out var foo)) { _foo = foo; } } [Benchmark] public void ContainGetNoExist() { if (LazyDictionary.ContainsKey("lindexi123")) { _foo = LazyDictionary["lindexi123"]; } } private object _foo; private Dictionary<string, object> LazyDictionary { get; } = new Dictionary<string, object>(); }
我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=19bm8i8js1ezb