C# - For vs Foreach - 巨大的性能差异
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15204950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# - For vs Foreach - Huge performance difference
提问by WoF_Angel
i was making some optimizations to an algorithm that finds the smallest number that is bigger than X, in a given array, but then a i stumbled on a strange difference. On the code bellow, the "ForeachUpper" ends in 625ms, and the "ForUpper" ends in, i believe, a few hours (insanely slower). Why so?
我正在对一种算法进行一些优化,该算法可以在给定的数组中找到大于 X 的最小数字,但后来 ai 偶然发现了一个奇怪的差异。在下面的代码中,“ForeachUpper”以 625 毫秒结束,“ForUpper”以几个小时结束(我相信,速度要慢得多)。为什么这样?
class Teste
{
public double Valor { get; set; }
public Teste(double d)
{
Valor = d;
}
public override string ToString()
{
return "Teste: " + Valor;
}
}
private static IEnumerable<Teste> GetTeste(double total)
{
for (int i = 1; i <= total; i++)
{
yield return new Teste(i);
}
}
static void Main(string[] args)
{
int total = 1000 * 1000*30 ;
double test = total/2+.7;
var ieTeste = GetTeste(total).ToList();
Console.WriteLine("------------");
ForeachUpper(ieTeste.Select(d=>d.Valor), test);
Console.WriteLine("------------");
ForUpper(ieTeste.Select(d => d.Valor), test);
Console.Read();
}
private static void ForUpper(IEnumerable<double> bigList, double find)
{
var start1 = DateTime.Now;
double uppper = 0;
for (int i = 0; i < bigList.Count(); i++)
{
var toMatch = bigList.ElementAt(i);
if (toMatch >= find)
{
uppper = toMatch;
break;
}
}
var end1 = (DateTime.Now - start1).TotalMilliseconds;
Console.WriteLine(end1 + " = " + uppper);
}
private static void ForeachUpper(IEnumerable<double> bigList, double find)
{
var start1 = DateTime.Now;
double upper = 0;
foreach (var toMatch in bigList)
{
if (toMatch >= find)
{
upper = toMatch;
break;
}
}
var end1 = (DateTime.Now - start1).TotalMilliseconds;
Console.WriteLine(end1 + " = " + upper);
}
Thanks
谢谢
采纳答案by SLaks
IEnumerable<T>
is not indexable.
IEnumerable<T>
不可索引。
The Count()
and ElementAt()
extension methods that you call in every iteration of your for
loop are O(n); they need to loop through the collection to find the count or the nth element.
将Count()
与ElementAt()
您在每个迭代调用扩展方法for
循环都为O(n); 他们需要遍历集合以找到计数或第 n 个元素。
Moral: Know thy collection types.
道德:了解您的收藏类型。
回答by Daniel Hilgarth
The reason for this difference is that your for
loop will execute bigList.Count()
at every iteration. This is really costly in your case, because it will execute the Select
and iterate the complete result set.
这种差异的原因是您的for
循环将bigList.Count()
在每次迭代时执行。在您的情况下,这确实很昂贵,因为它将执行Select
并迭代完整的结果集。
Furthermore, you are using ElementAt
which again executes the select and iterates it up to the index you provided.
此外,您正在使用ElementAt
which 再次执行选择并将其迭代到您提供的索引。