我在这里遇到了一个严重的难题。我正在调查应用程序中 WPF 组件的性能问题。

我们的 .net 应用程序非常大,并且几乎完全采用 Windows 窗体。作为新计划的一部分,我们使用丰富的 WPF 用户界面重写了我们的核心组件之一。有很多 WinForms<-->WPF 互操作性与此东西一起进行,以将其粘合在一起,我怀疑这可能与我所看到的内容有关。

当我在 ANTS 分析器中分析缓慢的操作时,我看到 UnsafeNativeMethods.IntGetMessageW 函数内部发生了很多活动。ANTS 报告的 CPU 活动与我们所有业务逻辑和 wpf 渲染内容的总和一样多。该函数没有使用循环的托管代码下线,因此无论 IntGetMessageW 正在做什么,这就是我所追求的。

我不是特别精通 win32 编程,但我知道该上下文中消息循环的基础知识。不过,我在这里看到的一切都不是我们手动执行的任何操作 - 在我们的代码中,我们没有直接与底层消息循环本身或可以在 WPF 调度程序上访问的任何更复杂的内容进行交互。

我们这里讨论的 WPF 组件是继承自 Window 编写的(即它不仅仅是一个控件/用户控件),我们使用 ShowDialog 来显示它,该逻辑来自我们的更高级别逻辑,该逻辑用于在该组件的旧 WinForms 版本上调用 ShowDialog。我们在 WPF 组件内部使用了一些 WindowsFormsIntegrationHost 控件,以保持与某些无法在 WPF 中重写的现有部分的兼容性。

我已经研究了好几天了,但从未发现很多可以继续的东西。我一直在寻找模糊相关的帖子,谈论输入消息(鼠标和键盘),但我不知道我可以做什么来验证这一点;我已经尝试过删除代码以删除所有可以删除的鼠标/键盘操作。

我很难到达任何地方,主要是因为这行代码是完全隔离的(不是我可以指出的实际上来自我们代码的任何内容的父级或子级),并且对于它正在做什么完全不透明。

下面是 ShowDialog 函数的 ANTS 调用图的图像,显​​示了到达此处的调用路径:alt text

我完全意识到这可能是 WPF 的一部分必须完成的事情(尽管我们在 WPF 中编写的其他组件不显示此行为),或者这只是 ANTS 分析器中的一个非常奇怪的错误,但是在这一点我需要通过某种方式来验证。如果有人能告诉我这里正在发生或可能发生的事情,或者向我指出某种我可以自己解决的方法,我将为你指引各种善业。

更新:为了回应下面的一些讨论,这是 ANTS 的另一种观点——这个观点更好地说明了我所遇到的困惑(这是“CPU 时间”模式下的 ANTS 视图)。我匆忙审查了部分代码,但没有与系统相关的功能:

alt text

感谢您的关注!

有帮助吗?

解决方案

我在搜索同一问题的信息时发现了这一点。我将补充我所知道的内容,看看是否有帮助:

我在 WinXP 机器上运行 - WPF 框架在 Vista 和 Win7 中比在 XP 中集成得更多。部分原因可能是 WPF 在 XP 桌面“之上”运行,而不是在其中运行。

我正在运行一个纯本机 WPF 应用程序 - 没有 WinForms 或其他代码。

我遇到了这个问题,试图确定为什么简单地滚动窗口会消耗 100% CPU 并且在执行此操作时出现卡顿。

运行 AQtime 性能分析器,我发现 IntGetMessageW 占据了 100% CPU 使用率的最大部分。这不是由于 IntGetMessageW 等待消息,而是该函数实际上正在执行的操作。

我还没有研究过的一件事是,也许 IntGetMessageW 从来就不是一个快速方法,也许 WPF 只是过度使用了它。WPF 中的数据绑定可能使用本机 Win32 消息泵来更新 WPF 中的依赖关系属性。如果是这种情况,可能是我的窗口有太多绑定。

其他提示

是的,这是正常的。任何 GUI 应用程序都是 总是 执行 GetMessageW(),等待 Windows 向其发送消息。这样做实际上并没有消耗 CPU 周期,只是在内部同步对象上阻塞,直到发出某种 UI 事件信号为止。

这当然会让分析 UI 应用程序变得困难,您确实需要单元测试来测试应用程序的子组件。

在分析应用程序时,您需要区分 所花费的时间 在方法和 CPU周期 消耗了。 许多分析工具都会向您显示某个方法所花费的总时间 - 在类似的情况下 GetMessageW 将会相当高。GUI 应用程序主线程的所有活动似乎都发生在该方法内。这不一定是问题,但是......这可能只是等待同步对象的主消息泵,而不是实际消耗的周期。

我建议您首先使用 ANTS 分析器中的采样功能来识别调用的方法 最经常 并将它们与消耗最多 CPU 周期的方法相关联。 完成此操作后,您可以决定在何处检测应用程序以进一步深入了解 CPU 密集度最高的地方的调用图。

您应该首先怀疑自己的代码。 像 WPF 或 Win32 基础结构这样的东西很少会导致性能差或 CPU 利用率高。问题可能出在您的实现中的某个地方 - 它可以帮助您全面了解 CPU 周期在程序中的使用情况。

我建议你也花一些时间 学习分析器的功能 才能最有效。 探查器可能是复杂且令人困惑的工具,除非您了解它们试图向您展示的内容。如果您还没有这样做,RedGate 的链接教程应该是一个很好的起点。例如,“时间轴”视图实际上可能是开始查看高 CPU 活动发生位置并将分析限制在执行代码的那些片段的好地方。

alt text

调用图是 ANTS 中的另一个有用的工具,因为它可以帮助您深入了解最昂贵的代码区域。关键是要确保您正在查看 总成本 而不仅仅是 总时间.

alt text

看起来你的消息泵正在抽水。看看你的消息队列中充满了什么样的消息可能会很有趣。你能在你的窗口上使用 Spy++ 看看发生了什么吗?

编辑

我误解了这个问题。

Hans Passant 是对的,您的程序只是在等待 GetMessage 来处理某些事件。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top