Visual Studio性能分析器 [clr.dll]

4

我正在尝试使用Visual Studio内置的探查器来对一个.NET应用程序进行性能剖析。在跟踪CPU样本时,我发现了一些奇怪的问题。在应用程序的某个部分,我有以下代码(为清晰起见进行了简化):

var requestObject = new RequestObject(parameters);
var result = GetResult(requestObject,"stringvalue");

我看到第二行使用了约10%的样本。然而,方法´GetResult()´只使用了约7%,其余似乎在[clr.dll]中。我知道clr.dll负责垃圾收集、JIT编译、上下文切换等等,而´GetResult()´方法相当复杂(跨越多个程序集,可能使用多个线程),因此一些操作需要在方法返回后执行,这并不是不可行的。´RequestObject´也有点复杂,所以可能与此有关。
我的问题是:我能否精确追踪此处发生的情况,以及我能做什么来使它更快?请注意,3%听起来不多,但´GetResult()´将在程序生命周期内被调用很多次,即使在测试时只运行一次。而且降低应用程序的响应时间非常重要。
非常感谢您提前的任何答案!

你必须选择正确的战斗。假设你可以让GetResult只需要1%而不是10%,那么你只能让你的程序快9%。你还有另外90%的潜在优化目标,那些你实际上可能拥有源代码的代码。你无法优化clr.dll中深藏的代码。 - Hans Passant
1
正如我所写的,GetResult()只是测试执行的一小部分,因为有一个相当强烈的初始化阶段。随着时间的推移,当GetResult()被调用了几千次时,我认为它将占据近乎100%的CPU时间。为了澄清,应用程序的响应时间几乎完全取决于GetResult()。那么,即使不触及GetResult(),是否有优化达到30%的潜力呢? - DukeOf1Cat
3个回答

3
您并不孤单,很多人都在尝试理解分析器的输出结果。StackOverflow上有很多类似的问题。我在一个大型的.NET应用程序中工作过,并尝试了各种性能分析工具,我知道这并不是人们所学的东西,而是这种方法实际有效。
首先,您可以在初始化期间进行一些采样,在基础运行时期间进行其他采样。您不必将两者堆叠在一起,并尝试猜测没有另一侧负载情况下另一侧的情况。
此外,如果您只查看CPU时间,您将错过任何由于额外的I/O而导致的加速机会。您不应假设没有,或者它微不足道。如果您确实找到了仅限于CPU的加速机会并予以修复,则您无法找到的部分将成为整个问题的较大部分。您可能会达到这样的程度:即使您找不到其他需要修复的问题,您也认为已经没有其他问题了,但实际上还有,并且可能很大。如果您自己进行采样,就可以清楚地了解哪些操作需要耗费时间。
您可能会说“但这不准确!”好吧,假如有一件事您可以修复并且可以节省90%的时间,但是您的查询不准确,显示它占用了80%或95%的时间,这会阻止您修复问题并获得10倍的加速吗?事实上,当您的目标是实际找到问题而不仅仅是测量它们时,问题越大,所需的样本就越少。

是的,我在相关帖子中读到了这个解决方案。整个周期大约需要500毫秒才能运行,因此我认为手动收集样本并在时间谱上均匀分布可能会很困难。如果我手动触发循环(通过连接到应用程序并调用方法),然后暂停,那么我很有可能总是在同一位置暂停,因为还要考虑反应时间等因素。您有自动化此过程的建议吗? - DukeOf1Cat
另外,如果 clr.dll 中完成的工作不是一件事,而是许多不同的事情呢?那么它们可能只会在我的样本中显示一次,那么我怎么知道是否找到了任何东西? - DukeOf1Cat
2
@Joel: 第一个问题:有几个答案:1)尝试一下,看看会发生什么;2)在你的半秒处理周围放置一个临时循环,比如100次。第二个问题:很可能是在clr.dll中,但堆栈可以告诉你请求它的代码部分。因此,例如,如果您看到它经常执行new GetResult,则可以检查是否可以重复使用旧内容等。重点是,您可以动用整个大脑来理解正在发生的事情,而不仅仅是纠结于某些数字的输出。 - Mike Dunlavey
1
@Joel:如果你愿意进行一些数学计算,可以参考这里的解释 - Mike Dunlavey

2
您可能会对免费下载的PerfView工具感兴趣。我同意Mike的观点,在这种情况下(Web请求),CPU可能不是主要因素,因此使用CPU分析器可能会出现误差。PerfView可以进行CPU分析,但它也能够进行“墙钟”分析(请参见PerfView欢迎页面上的“墙钟/阻塞时间”链接)。此视图显示了CPU和阻塞信息,但在解释数据时需要更加小心(您需要找到正确的线程并包括感兴趣的线程段)。如果这是一个ASP.NET应用程序,则有一个特殊的视图(ASP.NET线程时间堆栈)尤其值得关注(文档中也有相关介绍)。
坏消息是,没有什么可以代替理解分析器告诉你的内容,因此你需要花些时间学习这个工具向你展示的内容。我认为这是非常值得的,而且工具中还内置了 PerfView Videos 和相当不错的文档,可以帮助你解决问题,但你必须愿意投入一些时间(例如一个小时)。
好消息是,你的投资回报是非常可观的。你应该能够在一个小时内找到你特定的问题,并且只需投入几个小时的时间,你就能够找到几乎任何应用程序中的各种问题(即使你没有构建过)。这个工具非常强大,但随着强大的力量,也伴随着许多潜在的调查途径,以及可能误用数据和混淆的能力。

1
这篇文章虽然有些陈旧,但我想澄清一些事情。在当前的分析器实现中,每当你看到[]时,它意味着我们知道dll的名称,但无法解析其符号。一个原因是您没有在符号设置中选择Microsoft符号服务器。另一个可能性是模块是ngen(在这种情况下,您将看到[])。在这种情况下,您需要生成ngen pdb才能实际解析符号。一旦发生这种情况,您应该能够看到哪些函数正在使用cpu的哪个部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接