Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq效率问题-foreach vs聚合_Linq_Performance_Aggregate - Fatal编程技术网

Linq效率问题-foreach vs聚合

Linq效率问题-foreach vs聚合,linq,performance,aggregate,Linq,Performance,Aggregate,哪个更有效 //Option 1 foreach (var q in baseQuery) { m_TotalCashDeposit += q.deposit.Cash m_TotalCheckDeposit += q.deposit.Check m_TotalCashWithdrawal += q.withdraw.Cash m_TotalCheckWithdrawal += q.withdraw.Check } //Option 2 m_TotalCashDeposit =

哪个更有效

//Option 1
foreach (var q in baseQuery)
{
  m_TotalCashDeposit += q.deposit.Cash
  m_TotalCheckDeposit += q.deposit.Check
  m_TotalCashWithdrawal += q.withdraw.Cash
  m_TotalCheckWithdrawal += q.withdraw.Check
}

//Option 2
m_TotalCashDeposit = baseQuery.Sum(q => q.deposit.Cash);
m_TotalCheckDeposit = baseQuery.Sum(q => q.deposit.Check);
m_TotalCashWithdrawal = baseQuery.Sum(q => q.withdraw.Cash);
m_TotalCheckWithdrawal = baseQuery.Sum(q => q.withdraw.Check);

我想我要问的是,调用Sum基本上会在列表上枚举,对吗?所以,如果我调用Sum四次,这不是在列表上枚举了四次吗?如果只做一个foreach,那么我只需要枚举列表一次,不是更有效吗?

可能会,也可能不会,这取决于情况

唯一确定的方法是实际测量它

要做到这一点,请使用BenchmarkDotNet,下面是一个可以在控制台应用程序中运行的示例:

void Main()
{
    BenchmarkSwitcher.FromAssembly(GetType().Assembly).RunAll();
}

public class Benchmarks
{
    [Benchmark]
    public void Option1()
    {
//        foreach (var q in baseQuery)
//        {
//            m_TotalCashDeposit += q.deposit.Cash;
//            m_TotalCheckDeposit += q.deposit.Check;
//            m_TotalCashWithdrawal += q.withdraw.Cash;
//            m_TotalCheckWithdrawal += q.withdraw.Check;
//        }
    }

    [Benchmark]
    public void Option2()
    {
//        m_TotalCashDeposit = baseQuery.Sum(q => q.deposit.Cash);
//        m_TotalCheckDeposit = baseQuery.Sum(q => q.deposit.Check);
//        m_TotalCashWithdrawal = baseQuery.Sum(q => q.withdraw.Cash);
//        m_TotalCheckWithdrawal = baseQuery.Sum(q => q.withdraw.Check);
    }
}
是一个强大的性能度量库,它比简单地使用秒表要精确得多,因为它将使用统计上正确的方法和方法,并且还将JITting和GC等因素考虑在内


现在我年纪大了,也更聪明了,我不再相信使用秒表是衡量业绩的好方法。我不会删除旧的答案,因为谷歌和类似的链接可能会引导这里的人们寻找如何使用秒表来衡量性能,但我希望我在上面添加了一个更好的方法

下面的原始答案

测量它的简单代码:

Stopwatch sw = new Stopwatch();
sw.Start();
// your code here
sw.Stop();
Debug.WriteLine("Time taken: " + sw.ElapsedMilliseconds + " ms");
sw.Reset(); // in case you have more code below that reuses sw

您应该多次运行代码,以避免JITting对计时产生太大的影响。

我继续分析了这一点,发现您是正确的

每个Sum()有效地创建自己的循环。在我的模拟中,我让它对包含20319条记录的SQL数据集求和,每个记录都有3个可求和字段,并发现创建自己的循环有2倍的优势


我曾希望LINQ能够优化这一点,并将整个负担推到SQL server上,但除非我将sum请求移动到初始LINQ语句中,否则它会一次执行一个请求。

我运行了Lasse建议的测试,发现使用一个foreach循环比使用多个sum更有效。感谢Lasse和Duck运行测试并提供进一步支持。