【发布时间】:2020-04-15 00:11:01
【问题描述】:
在我们软件的一个版本和新出现的 beta 版本之间,循环遍历 DataTable 中所有 DataColumns 的方法存在显着延迟(该循环也在所有行的循环内)。
这是(简化但逻辑完整的)代码,两个版本都相同:
Stopwatch foretimer = Stopwatch.StartNew();
foreach (DataColumn dc in ds.Tables[0].Columns)
{
Stopwatch foreinnertimer = Stopwatch.StartNew();
RenderProfile.addProfile("Rows.StandardCellContents.foreEachColumn-Qty", 1);
if (renderColumn(dc))
{
Stopwatch trtimer = Stopwatch.StartNew();
temp = TokenReplacement.replaceNonCachedTokens(temp, rsa, dc, dr);
RenderProfile.add("Rows.StandardCellContents.replaceCellTokens", trtimer.ElapsedMilliseconds);
RenderProfile.add("Rows.StandardCellContents.replaceCellTokens-Qty", 1);
RenderProfile.add("Rows.StandardCellContents.foreEachColumn-inner", foreinnertimer.ElapsedMilliseconds);
}
RenderProfile.add("Rows.StandardCellContents.foreEachColumn-inner-ALL", foreinnertimer.ElapsedMilliseconds);
}
RenderProfile.add("Rows.StandardCellContents.foreEachColumn", foretimer.ElapsedMilliseconds);
(TokenReplacement.replaceNonCachedTokens 中的底层代码有一些变化,但配置文件时间并没有明显不同)
这些示例适用于相同的输入,它有 1000 行和 24 列,其中 19 列被“渲染”。
这会在旧版本上生成这些配置文件值:
Rows-Qty:1000
Rows.StandardCellContents.foreEachColumn-Qty:24000
Rows.StandardCellContents.replaceCellTokens:14ms
Rows.StandardCellContents.replaceCellTokens-Qty:19000
Rows.StandardCellContents.foreEachColumn-inner:14ms
Rows.StandardCellContents.foreEachColumn-inner-ALL:14ms
Rows.StandardCellContents.foreEachColumn:2032ms
以及新版本上的这些配置文件值:
Rows-Qty:1000
Rows.StandardCellContents.foreEachColumn-Qty:24000
Rows.StandardCellContents.replaceCellTokens:59ms
Rows.StandardCellContents.replaceCellTokens-Qty:19000
Rows.StandardCellContents.foreEachColumn-inner:66ms
Rows.StandardCellContents.foreEachColumn-inner-ALL:67ms
Rows.StandardCellContents.foreEachColumn:9174ms
这怎么可能? 不幸的是,即使在旧的(更快的)版本中,仅对 DataColumns 的迭代 (Rows.StandardCellContents.foreEachColumn) 大约需要 2 秒,但绝对是奇怪的是新版本一直是+7-8秒!!
它们都在相同版本的 .NET (4.0) 上运行。我在我们所做的更新中找不到任何会改变 DataTable 结构的内容。是否有与 DataSet/DataTable 相关的内容可能会减慢所有列上的 for each 循环??
非常感谢任何有关如何进一步分析此问题的指导或建议。
【问题讨论】:
-
@mjwills 我不认为您没有看到涉及的代码.. 我想您必须相信我的话,所涉及的 2 个数据表具有相同的编号行,相同的列,以及所有这些单元格中的相同数据.. 但我向你保证他们会这样做。仅使用我展示的代码,是否清楚简单的 foreach 迭代在新版本上花费了 7 秒以上?我想我正在寻找围绕 DataTable 和 DataColumn 集合的任何“已知性能陷阱”,或者关于如何进一步挖掘的建议。
-
验证它是
foreach的简单方法是在不执行任何循环的情况下对foreach计时——将代码注释为renderColumn和TokenReplacement.replaceNonCachedTokens。 -
@ilasno 您是否可以使用一些性能分析工具来分析您的应用程序,例如使用
dotTrace JetBrains。如果您是,查看性能快照会很有帮助。即使您没有dotTrace的许可证,您也可以下载并使用试用版 30 天。 -
renderColumn()是做什么的?会不会和老版本不一样? -
好吧,我觉得很害羞.. 我认为我的计时器和时间记录语句的战略布局是把责任直接归咎于实际的迭代,但这似乎是一个错误的假设。我仍然不确定为什么
Rows.StandardCellContents.foreEachColumn-inner-ALL没有显示更多时间,因为它应该对每次迭代的时间求和.. 但是当我注释掉foreach中的所有代码时,缓慢的性能就会消失。我正在深入挖掘,感谢所有给我时间的人。 @HereticMonkey 如果您想添加您的评论作为答案,我会接受!
标签: c# asp.net foreach datatable