为什么 Any 比 contains 慢? [英] Why is Any slower than Contains?
问题描述
我设计了以下测试:
var arrayLength=5000;
object[] objArray=new object[arrayLength];
for(var x=0;x<arrayLength;x++)
{
objArray[x]=new object();
}
objArray[4000]=null;
const int TestSize=int.MaxValue;
System.Diagnostics.Stopwatch v= new Stopwatch();
v.Start();
for(var x=0;x<10000;x++)
{
objArray.Contains(null);
}
v.Stop();
objArray.Contains(null).Dump();
v.Elapsed.ToString().Dump("Contains");
//Any ==
v.Reset();
v.Start();
for(var x=0;x<10000;x++)
{
objArray.Any(o=>o==null);
}
v.Stop();
objArray.Any(x=>x==null).Dump();
v.Elapsed.ToString().Dump("Any");
//Any Equals
v.Reset();
v.Start();
for(var x=0;x<10000;x++)
{
objArray.Any(obj=>object.Equals( obj,null));
}
v.Stop();
objArray.Any(obj=>object.Equals( obj,null)).Dump();
v.Elapsed.ToString().Dump("Any");
null 不存在时的结果:
The results when null is not present:
包含假 00:00:00.0606484
Any == False 00:00:00.7532898
任何对象.Equals False 00:00:00.8431783
当元素 4000 处存在 null 时:
When null is present at element 4000:
包含真实的 00:00:00.0494515
Any == True 00:00:00.5929247
任何对象.等于真 00:00:00.6700742
当元素 10 出现 null 时:
When null is present at element 10:
包含真实的 00:00:00.0038035
Any == True 00:00:00.0025687
Any True 00:00:00.0033769
所以当物体靠近前面时,Any
稍微快一点;当它在后面时,它要慢得多.为什么?
So when the object is near the front, Any
is slightly faster; when it's at the back, it's much much slower. Why?
推荐答案
Any
将不得不为它检查的每个元素调用一个委托(额外的 callvirt
指令是不太可能被 JIT 内联).Contains
仅执行该检查.这就是 Any
更慢的原因.我怀疑 Any
在很早看到元素时看起来比包含更快的事实是基准不能轻易反映它,因为它们非常接近.方法调用的设置时间是这种情况下完成的大部分工作(而不是实际的搜索操作).
Any
will have to call a delegate for every element it checks (an extra callvirt
instruction which is unlikely to get inlined by the JIT). Contains
only performs that check. That's why Any
is slower. I suspect the fact that Any
looks faster than contains when the element is seen very early is that the benchmark can't reflect it easily since they are very close. The setup time for the method call is the majority of the work done in that case (rather than the actual searching operation).
The anonymous method:
--- C:\Users\Mehrdad\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs
Console.WriteLine(s.Any(a => a == 1));
00000000 xor eax,eax
00000002 cmp ecx,1
00000005 sete al
00000008 ret
Relevant part of Enumerable.Any code:
...
00000051 mov edx,eax
00000053 mov rcx,qword ptr [rbx+8]
00000057 call qword ptr [rbx+18h] // calls the anonymous method above
0000005a movzx ecx,al
0000005d test ecx,ecx
...
这篇关于为什么 Any 比 contains 慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!