【问题标题】:Freezing managed threads冻结托管线程
【发布时间】:2012-02-17 11:08:24
【问题描述】:

我正在开发一个相当大的应用程序,它负责进行实时运动跟踪和摄像机运动控制。它的任务是:

  • 运动跟踪(由本机模块完成,该模块对来自网络摄像机的视频流进行解码,并通过回调将最大 1280x720 像素的图像缓冲区和跟踪结果提供给托管应用程序)
  • 每秒大约 20 次从平移/倾斜硬件接收定位反馈数据并向其发送运动数据,以及从/向摄像机发送缩放命令
  • 显示包括实时可视化在内的图像数据
  • 图像和会话数据的编码和写入
  • 视频的自动后处理由另一个进程完成

该应用程序使用 .NET 4.0 并具有 WPF 用户界面。

托管线程冻结

从一开始,我们就不得不面对冻结在 500 到 1500 毫秒之间的托管线程,这对于像这样的实时应用程序来说实在是太多了。

为了查明这些挂起何时发生,我创建了一个线程,其唯一任务是一直休眠 100 毫秒。然后我计算了睡眠真正花了多长时间,并准确地得到了相机停止移动的时间。它工作非常可靠,线程都同时挂起!

非托管线程不会冻结

虽然所有托管线程冻结非托管线程工作没有任何问题。我们通过独立于应用程序的托管部分编写的日志来检查这一点。

分析

我试图找出可能导致这种行为的现象:

  • 当我们遇到这些问题时,整台机器会变慢:Windows 响应非常缓慢(例如,目录列表在 Windows 资源管理器和我的应用程序中都挂起半分钟,或者启动应用程序的时间非常长)
  • 我们同时读取和写入数千个文件(跟踪和后处理应用程序),这可能会使窗口超负荷
  • GUI 的响应变得非常缓慢
  • 该应用程序使用大约 1.3GB 的虚拟内存(根据 Process.VirtualMemory64)/ 500MB 的工作集内存 (Process.WorkingSet64) - 是不是其中一些被交换到了硬盘上? (如何检查或解决?)
  • 当然,如果我们终止进程,Windows 会再次快速响应,但 Windows 需要一段时间才能再次正常响应

非常感谢您提供有关如何调查此问题的提示。非常感谢!

【问题讨论】:

  • 您所描述的听起来像是颠簸:en.wikipedia.org/wiki/Thrashing_%28computer_science%29 尝试使用 FileMon 和 DiskMon 来查看磁盘访问实际发生了什么。
  • 运行 taskmgr.exe,进程选项卡。查看+选择列并勾选“页面错误增量”。通常的下一个结论是“啊,需要更多 RAM”。
  • @HansPassant:我在“页面错误增量”下得到的值最高为 70.000。这是否指向“颠簸”? (顺便说一句:您可以为这篇文章创建一个新答案而不是发表评论)

标签: c# .net multithreading


【解决方案1】:

【讨论】:

  • 感谢提示,我们解决了:有一些代码创建了很多堆对象。我们现在阻止创建这么多对象并在需要充分性能时收集 GC,因此 GC 只是在之后完成(--> GCSettings.GCLatencyMode)。
【解决方案2】:

我建议您在遇到性能问题时进行进程转储。您可以通过多种方式执行此操作(来自 SysInternals 的 taskmgr.exe 或 procdump.exe)。进行完整的内存转储。

获得 .dmp 文件后,您可以使用 windbg(或 Visual Studio 2010)对其进行分析。对于托管进程,您需要加载 sos.dll 扩展。

那里有很多很好的windbg资源,但这里有一些对我有帮助:

1) Tess Fernandez video(ASP.NET 进程,但技术相同)

2) WinDbg cheatsheet

内存分析将能够在您遇到问题时为您提供堆栈 (!clrstack) 并告诉您确切的罪魁祸首。

【讨论】:

    猜你喜欢
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多