Val*_*ita 5 c# multithreading profiling garbage-collection dottrace
我试图找出为什么我的应用程序随着时间的推移变得更慢。应用程序将要做的工作打包成可以并发执行的批处理。每一批都必须等待前一批完成。批处理在更新函数内每~30 毫秒执行一次。在代码中,它看起来像这样:
List<List<Action>> batches = new List<List<Action>>(); // class member
foreach (var batch in batches) // inside of the update function
{
Parallel.ForEach(batch, action => action());
}
Run Code Online (Sandbox Code Playgroud)
几天后,我发现执行所有批处理所需的时间越来越长。起初,执行大约需要 15 毫秒,然后几天后它需要超过 100 毫秒。我的目标是找出执行时间不断增加的原因。
在调试的时候,我发现批次数量和每批次的动作数量保持不变。
使用 dotTrace 进行分析表明,有时批处理中的一个操作需要更长的时间,并且Parallel.ForEach将(并且应该)等到所有先前的操作完成。在启动应用程序后立即进行分析时,仅每隔几百次更新就会出现延迟。几天后,几乎每次更新都会发生延迟。
这是它在分析器中的样子;我用不同深浅的绿色标记了各个更新周期并给它们编号。如您所见,第二次更新有明显的延迟(黄色)。
在黄色期间,没有其他线程在做工作(至少根据分析器)。当一个一个的选择线程时,除了一个线程之外的所有线程都不在一个动作上工作。正如您在下一张图片中看到的,仍在处理某个操作的线程没有显示任何 CPU 负载,并且所有时间都花在ntdll.dll.
在这种情况下,对 的调用GetEnumerator大约需要 24 毫秒,但我已经看到类似ToString()或ToArray()太多的函数冻结。
我观察到的相关内容:
ntdll.dll| 归档时间: |
|
| 查看次数: |
364 次 |
| 最近记录: |