【问题标题】:How can I optimize the performance of my application based on a profile?如何根据配置文件优化应用程序的性能?
【发布时间】:2011-04-12 16:06:41
【问题描述】:

我分析了我的应用程序并发现不是我的函数导致了我看到的延迟,而是 winform 函数。我该如何纠正?有关说明,请参见:

这是分析的结果:

【问题讨论】:

  • 您的程序总体上在做什么?用户界面是否在做一些奇怪的事情,你是否注意到使用它时速度很慢?

标签: c# winforms performance profiling red-gate-ants


【解决方案1】:

你无法解决这个问题。

框架正在调用由 Windows API 公开的 DispatchMessage function,该 API 用于将通过调用 GetMessage 函数检索到的消息发送到特定窗口的窗口过程。

这里的“慢”部分是 Windows 本身。当这成为您的瓶颈时,您的应用程序已充分优化,您无能为力。

此外,这些配置文件结果不一定告诉您此功能。相反,他们告诉你它被调用很多(“命中计数”)。这个想法是,经常被调用的函数是代码中的“热点”,值得花一些额外的时间来优化它们的实现(更划算)。但是,在这种情况下,该函数会被大量调用,因为它是 Windows 为您的应用程序处理消息的方式。在非托管代码和本机 Windows API 的世界中,消息有点像您在 .NET 代码中使用的事件。由于任何有趣的事情都必须引发事件,因此负责调用或分派这些事件(消息)的函数必然会被调用很多次。

【讨论】:

  • 我明白了,非常感谢,不过我可以做得更好吗?每个事件都在发送消息?
  • @Blue Gene:我必须查看您的更多代码才能为您提供有关优化的更多具体提示。但我严重怀疑你还能做些什么。您获得的配置文件结果毫无用处——它们告诉您,要么 .NET Framework 的内部代码很慢,要么 Windows 本身很慢。由于您没有编写该代码,因此无法对其进行优化。不过,这没什么大不了的,因为其他所有程序员都必须在同样的约束下工作。您的应用不太可能比他们的慢。
【解决方案2】:

Windows 应用程序通常包含一个顶级循环,它们在其中等待鼠标移动/点击和键盘敲击等外部事件或内部生成的事件。当一个事件发生时,它会调用适当的处理程序,这可能会做一些事情,也可能做很多事情。通常它会遍历一个相当广泛和深入的调用树,但如果它很快完成,它就会返回等待。

看起来表现良好的应用在等待下一个外部事件时花费了大部分时间。

表现不佳的应用程序大部分时间都在遍历调用树以响应事件。

提高其性能的方法是找到瓶颈并消除它们。瓶颈几乎总是由调用树中的函数调用组成,在你的代码中,你不知道这些调用很昂贵。不在代码中的调用树部分是您无能为力的,但如果您可以避免调用它们,您就有机会获得加速。

就像您是一名经理一样,试图查看您的员工是否在浪费时间,您也可以不经通知就进来看看他们在做什么。 在软件中,this is how you can do that

小心那些让你感到困惑的分析器,比如 1) 告诉你例程的“自我时间”,2) 告诉你一个函数被调用了多少次,3) 给你一个庞大但几乎不相关的图表或表格,或者4) 很多有趣但通常不相关的线索,例如缓存未命中和线程切换。

找到瓶颈很容易,因为如果它们很小,它们并不是真正的瓶颈,如果它们很大,在它们浪费的时间里,它们就在堆栈上,等待你注意。 Here's more on that subject.

【讨论】:

  • @Mike 但分析器(RedGates Ants)显示大部分时间都花在调用树中不是我的代码的部分,如图所示。
  • @Blue:我似乎看不到照片。 (它涉及一些大的下载内容。)没关系。当我听到“大部分时间都花在……”时,我的耳朵会竖起来,因为这听起来像是基本的分析器混淆。自我时间?请忽略这一点 - 它没用。包容时间?墙还是 CPU 时间?墙上的时间是你需要的。按功能还是按线?按行是你需要的。命中数 - 没用。毫秒还是百分比?百分比是你需要的。您正在寻找的是代码中在堆栈(即活动)上占墙时间的高百分比的行。有这些吗?
  • 这似乎是对配置文件引导优化的一般介绍,而不是对特定问题的回答。考虑到我如何改写问题的标题,也许这是我的错。这里的问题是提问者想知道如何优化框架内部的 API 调用。这是不可能的。
  • @Cody:对。他说“发现不是我的功能导致了延迟”以及“我该如何纠正这个问题”。关键是一个例程的“花费时间”是否也被调用它的行“花费”,依此类推。出于某种原因,这似乎没有被普遍理解。
  • 你是对的。我没有意识到这并没有被普遍理解。我当然不是说你的答案是错误的。但绝对有可能框架正在对DispatchMessage 进行内部调用,而这并不是询问者明确编写的代码的错。它是内部实现的一部分,而不是容易重写或优化的东西。显然我同意他应该检查调用堆栈,看看是什么导致框架在内部调用该函数,但这很可能是一个死胡同。 (另外,我同意你的 cmets;分析软件还有很多不足之处。)
猜你喜欢
  • 2012-12-10
  • 2013-06-25
  • 1970-01-01
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
相关资源
最近更新 更多