3

哪个更有效率?

//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 不是更有效,所以我只需要枚举列表一次吗?

4

2 回答 2

6

它可能会,也可能不会,这取决于。

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

为此,请使用 BenchmarkDotNet,这是一个可以在LINQPad或控制台应用程序中运行的示例:

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);
    }
}

BenchmarkDotNet是一个强大的性能测量库,比简单地使用 Stopwatch 准确得多,因为它将使用统计上正确的方法和方法,并且还会考虑 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 对您的计时产生太大影响。

于 2009-08-12T16:57:54.957 回答
2

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

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

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

于 2009-08-12T17:17:38.083 回答