C# 哪一个比较快:查询语法与循环
下面的代码提供了两种生成总和小于100的整数对的方法,它们根据与0,0的距离按降序排列C# 哪一个比较快:查询语法与循环,c#,performance,loops,code-readability,linq-query-syntax,C#,Performance,Loops,Code Readability,Linq Query Syntax,下面的代码提供了两种生成总和小于100的整数对的方法,它们根据与0,0的距离按降序排列 //approach 1 private static IEnumerable<Tuple<int,int>> ProduceIndices3() { var storage = new List<Tuple<int, int>>(); for (int x = 0; x < 100; x++)
//approach 1
private static IEnumerable<Tuple<int,int>> ProduceIndices3()
{
var storage = new List<Tuple<int, int>>();
for (int x = 0; x < 100; x++)
{
for (int y = 0; y < 100; y++)
{
if (x + y < 100)
storage.Add(Tuple.Create(x, y));
}
}
storage.Sort((p1,p2) =>
(p2.Item1 * p2.Item1 +
p2.Item2 * p2.Item2).CompareTo(
p1.Item1 * p1.Item1 +
p1.Item2 * p1.Item2));
return storage;
}
//approach 2
private static IEnumerable<Tuple<int, int>> QueryIndices3()
{
return from x in Enumerable.Range(0, 100)
from y in Enumerable.Range(0, 100)
where x + y < 100
orderby (x * x + y * y) descending
select Tuple.Create(x, y);
}
本代码摘自比尔·瓦格纳的《有效C》一书第8项。在整篇文章中,作者更多地关注代码的语法、紧凑性和可读性,但很少关注性能,几乎没有讨论它
所以我基本上想知道,哪种方法更快?通常性能更好的是什么:查询语法还是手动循环
请详细讨论,如有,请提供参考:- 分析是事实,但我的直觉是循环可能更快。重要的是,100次中有99次的性能差异在总体方案中并不重要。使用更具可读性的版本,当您以后需要维护它时,您未来的自我将感谢您。虽然这并不能严格回答您的问题,但从性能角度来看,我建议将x+y逻辑合并到迭代中,因此:
for (int x = 0; x < 100; x++)
for (int y = 0; y < 100 - x; y++)
storage.Add(Tuple.Create(x, y));
每个函数运行1000次: 循环频率:2623毫秒 查询:2821MS
看起来很有逻辑,因为第二个只是第一个的合成糖。但是我会使用第二个,因为它的可读性。查询必须在某个点上转移到循环中,所以一定会有一些开销,即使差异可以忽略不计。出于好奇,你能解释一下这种排序吗?:orderby x*x+y*y降序我不明白它是如何工作的第二个会快得多,因为它除了构建查询之外什么都不做,所以在做了ToList之后,您将能够进行比较;诺特:这是距离0clever的距离,但它会使速度与需要更改的其他函数的比较产生偏差:从Enumerable.Range0中的y开始,100 xIn老实说,任何半体面的优化编译器都应该使此更改可以忽略不计。如果我可以补充,在第二种方法中,编译器可以更好地理解代码的目的,因此,它可以更恰当地对其进行优化。也许现在,即使进行了优化,第一种方法也会运行得更快,然而,在不久的将来,我们可能会从第一种方法中获得更好的性能。对于一个小型学习项目来说,评测可能有点过火。把数字从100增加到1000000是很容易的,只是用秒表来测量时间上的差异。@菲尔-我会考虑分析,即使你没有使用一个花哨的工具来做。出于好奇,当你把它画出来的时候,您是否确实从第二个函数中枚举了查询,例如使用.ToList或其他什么?如果使用ToList,则大约需要3毫秒;