【发布时间】:2009-03-09 21:42:53
【问题描述】:
由于某种原因,当元素已经存在于HashSet 中时,HashSet 上的Add 操作似乎比Contains 操作慢。
这是证据:
Stopwatch watch = new Stopwatch();
int size = 10000;
int iterations = 10000;
var s = new HashSet<int>();
for (int i = 0; i < size; i++) {
s.Add(i);
}
Console.WriteLine(watch.Time(() =>
{
for (int i = 0; i < size; i++) {
s.Add(i);
}
}, iterations));
s = new HashSet<int>();
for (int i = 0; i < size; i++) {
s.Add(i);
}
// outputs: 47,074,764
Console.WriteLine(watch.Time(() =>
{
for (int i = 0; i < size; i++) {
if (!s.Contains(i))
s.Add(i);
}
}, iterations));
// outputs: 41,125,219
为什么Contains 比Add 对已经存在的元素更快?
注意:我正在使用来自另一个 SO 问题的 Stopwatch 扩展名。
public static long Time(this Stopwatch sw, Action action, int iterations) {
sw.Reset();
sw.Start();
for (int i = 0; i < iterations; i++) {
action();
}
sw.Stop();
return sw.ElapsedTicks;
}
更新:内部测试表明,较大的性能差异仅发生在 x64 版本的 .NET 框架上。使用 32 位版本的框架 Contains 似乎以相同的速度运行(事实上,在某些测试运行中,带有 contains 的版本似乎运行速度慢了一个百分点)在 X64 版本的框架上,带有 contains 的版本似乎运行速度快约 15%。
【问题讨论】:
-
对于 32 位测试,你是在 32 位机器上运行,还是在虚拟机上运行,还是通过指定 x86 目标来编译和运行 WOW64 下的 32 位框架?我不知道这会有所不同,但这是可能的。
-
我在虚拟机中进行了 32 位测试
-
您是否尝试过将测试包含添加功能移到添加上方然后测量时间?你会发现差异可以忽略不计..
-
在我的测试用例中,移动这两种方法后,Add 块有时比 Contains Add 运行得更快。
标签: c# performance hashset