title | author | date | CreateTime | categories |
---|---|---|---|---|
C# 字典 Dictionary 的 TryGetValue 与先判断 ContainsKey 然后 Get 的性能对比 |
lindexi |
2019-11-29 10:13:19 +0800 |
2018-09-08 15:33:40 +0800 |
C# |
本文使用 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