有人可以帮我找到这段代码中的瓶颈吗?

Posted

技术标签:

【中文标题】有人可以帮我找到这段代码中的瓶颈吗?【英文标题】:Can someone help me find the bottleneck in this code? 【发布时间】:2016-05-22 15:10:29 【问题描述】:

我在一个循环中运行了大约 5000 次的以下代码块。

IQueryable<IGrouping<int?, StatusLog>> allLogs = db.StatusLogs
    .Where(sl => sl.ID.Value.Equals(foo))
    .GroupBy(sl=>sl.bar);

List<StatusLog> statusLogs = new List<StatusLog>();

foreach (var group in allLogs)

    // do stuff that adds to statusLogs


if (statusLogs.Count > 0)

    // do stuff

我试图在代码中找到一个似乎无缘无故需要大约 50 毫秒的瓶颈。

即使allLogs 为空且没有组,也需要 50 毫秒才能步入

foreach (var group in allLogs)

if (statusLogs.Count > 0)

单步执行var groupin allLogs 的评估只需要大约3 毫秒,那么当foreach 循环内的代码甚至没有运行时,如何跳转到下一条语句需要50 毫秒呢?

【问题讨论】:

您必须提供更多代码。 50ms 与系统时钟分辨率相比是相当短的时间。这次你是怎么衡量的?您确定其他进程在测量时没有使用大量 CPU 吗? 您认为往返数据库是免费的吗? 【参考方案1】:

将其拆分为数据库访问,然后是 for 循环和每个时间(使用 StopWatch 类)

var allLogs = db.StatusLogs
    .Where(sl => sl.ID.Value.Equals(foo))
    .GroupBy(sl=>sl.bar).ToList();// tolist forces query to run now

foreach (var group in allLogs)

    // do stuff that adds to statusLogs

【讨论】:

【参考方案2】:

这是因为allLogs 本质上是惰性 ——它实际上会在foreach 中第一次枚举时访问数据库(请参阅“延迟查询执行”here)。如果您像下面这样预先实现集合,您会看到它快速通过foreach

db.StatusLogs
    .Where(sl => sl.ID.Value.Equals(foo))
    .GroupBy(sl=>sl.bar)
    .ToList();  // <-- pull the query results into memory

【讨论】:

据记录,这并没有解决问题,它只移动了 50ms 发生的地方。我刚刚接受了一个答案,希望一连串的反对票能结束。 @iMassakre 这里没有要解决的问题。无论您在哪里进行数据库调用都需要时间。我只是试图解释为什么在你的情况下单步执行 foreach 需要时间。 哦,我明白你的意思了。那么我想没有办法解决这个问题。生成一个包含 5000 个项目的报告需要大约 13 分钟,这似乎很疯狂。

以上是关于有人可以帮我找到这段代码中的瓶颈吗?的主要内容,如果未能解决你的问题,请参考以下文章

有人可以帮我修改这个 Excel VBA 代码吗?

有人可以帮我并行化这个 C++ 代码吗?

这个解压包是做啥的?有人可以帮我理解几个字母吗?

在Java中查找数组中的最小和最大数

堆的算法排列 JavaScript 和递归的堆栈?

有人可以帮我修复错误 pls-00049 吗?