有人可以帮我找到这段代码中的瓶颈吗?
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 group
和in 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 分钟,这似乎很疯狂。以上是关于有人可以帮我找到这段代码中的瓶颈吗?的主要内容,如果未能解决你的问题,请参考以下文章