繁体   English   中英

使用秒表分析.NET应用程序

[英]Profiling .NET applications with Stopwatch

似乎没有免费的* .NET性能分析器可以逐行进行分析。 因此,我正在研究使用秒表进行分析。

*在自由中免费,即许可包括商业应用。

编辑:回应那些告诉我“买一个探查器”的人,我想,但如果我可以花那么多钱,我会花在别的东西上。 我试图说服我的老板说一个分析器值得,但运气不好。 这个问题主要基于好奇心。 我永远不会认为秒表是真正的探查者的替代品。

我有一个小测试应用程序(用C#编写),用于衡量在每行使用秒表时的性能差异。 测试代码是这样的:

int n = 100;
BigInteger f = 1;
for (int i = n; i > 1; i--)
{
    f *= i;
}

以下是完整代码: http//pastebin.com/AvbQmT32

我为每行代码都有一个秒表。 这是我的“探查者”。 我整个节目也有一个秒表。 这是我的'profiler profiler'。

我将程序配置为发布模式,任何CPU(在x64计算机上),并禁用优化。

当我在禁用探查器的情况下运行程序时,我会得到这样的结果:

             Line             |  Ticks
------------------------------|----------
                              |
Total time:                   |       359

当我在启用了探查器的情况下运行它时,我会得到这样的结果:

             Line             |  Ticks
------------------------------|----------
                              |
int n = 100;                  |         3
BigInteger f = 1;             |        12
for (int i = n; i > 1; i--)   |       325
{                             |
    f *= i;                   |       539
}                             |
                              |
Total time:                   |      1710
Stopwatch overhead:           |       831

理想情况下,在两种情况下花在代码上的时间应该相等,但看起来Stopwatches的开销在它们自己的经过时间内出现。

现在,需要对程序的每一行进行剖析通常没有意义,因为它通常可以通过分而治之的方法更好地工作。 您通常可以从分析代码块开始,并缩小任何性能问题。

此外,在大多数应用程序中,平均代码行将比测试程序中的代码慢很多。 这意味着秒表开销会减少。

但是,使用Stopwatches时仍然存在开销,特别是如果你经常使用。

所以问题是:

使用Stopwatches进行性能分析的最有效方法是什么? 如何最大限度地减少开销? 围绕一个声明包装秒表是否值得?

感谢您的反馈。

考虑到我们经常通过单一责任原则直观地编程,不仅在类型方面而且在功能方面也是如此,我想说的是,没有任何形式的分析应用程序 您将更感兴趣的是分析每一行的“单一责任”。

当然,您需要获得信息的情况也是如此。 但是不要在所有应用程序中使用它,而是在函数的单个部分或单个函数中使用它。 在这种情况下, StopWatch是最佳选择。 考虑到StopWatch.NET Class方面它甚至最小的开销。 你不应该看绝对 ,而是看相对价值。

希望这可以帮助。

你不应该看到确切的数字,你应该寻找相对的差异。 这样您就可以识别问题区域。 您正在寻找可以解决性能问题的优化场所。

如果您正在开发性能实际上是问题的级别的代码,并且您需要对其进行分析以找到有问题的代码,那么购买一个工具来为您执行此任务将不仅仅是在节省的时间内收回成本。 Visual Studio Premium附带的分析器是我推荐的。

您是否尝试过查看CInject: http ://codeinject.codeplex.com/documentation? 它基本上将代码注入DLL。 开箱即用它似乎有性能监控,但它也允许您创建自己的代码注入。 似乎非常适合您尝试做的事情。

第一件事是第一件事:你的结果并不令人惊讶。 如果你使用的是商业分析器,你会看到类似的东西:你的程序在被分析时需要花费更长的时间才能运行。 您设置分析器的粒度越精细,您可以预期的时间就越长。 当您认为像“i> 1”和“i--”这样的语句可能会作为单处理器指令执行时,很明显为什么分析特定行的执行时间比执行行本身要花费更长的时间。

分析增加程序的整体运行时间这一事实不应该成为一个问题; 正如其他几个人所提到的那样,重要的不是程序运行的绝对时间,而是将各个部分的运行时间相互比较以找出瓶颈。 但还有另一个问题。 秒表将使用底层操作系统中的高频计时器(如果有的话); 但即使这可能还不够高。 我的Windows 7 64位i5-2400(四核3.10 GHz)上的高频定时器每秒发送3,020,556次。 听起来很多; 但按照这个速度,处理器可以在刻度线之间执行一千条指令。 这意味着如果您正在尝试测量执行单个指令所需的时间,那么您要么处于低位还是要超越。

您最好在方法级别进行性能分析。 即使这样,你也会遇到频率问题,特别是如果你有一些精心设计的方法。 但结果将比在线级别更可靠; 一旦您确定了导致瓶颈的方法,您可以直接检查它以确定如何优化它以更好地执行。

所有这些都抛弃了许多与一般性能分析相关的警告,这不在本文的讨论范围之内。 确保您对该主题进行额外的研究,以了解您应该如何解释您获得的结果。 作为一个简单的例子,您的分析可能会揭示程序中的大部分时间都花在特定方法上; 但这是否意味着方法本身就是问题,或者其他方法经常调用它? 回答这类问题是分析的真正困难所在。

您是否将没有分析器的总时间与分析器在调试模式下的时间进行了比较? 我的第一个猜测是额外的时间出现,因为秒表的额外声明阻止了一些寄存器或循环优化。 因此额外的时间可能来自缺失的优化而不是秒表的一些时间损失。

然而,话虽如此,即使秒表具有高分辨率,我认为你会注意到一些时间错误测量小到一行代码。 例如'int n = 100'是汇编中的一行,因此在技术术语中我认为它只有1个刻度。 从运行到运行,您在数字中注意到多少变化? 如果您得到的变化占平均值的很大一部分,那么该值实际上并没有给您那么多信息。

也许您应该考虑分析方法调用时间,而不是单行。 毕竟,方法调用通常是调用代码中的单行。 另一个有趣的方法是使用日志库来记录方法入口和退出,例如,像这样(使用log4net作为选择的记录器):

public string MyMethod(string arg)
{
    string result = null;

    if (logger.IsDebugEnabled) logger.Debug("->MyMethod(" + arg + ")");

    // do stuff
    result = "Hello world!";

    if (logger.IsDebugEnabled) logger.Debug("<-MyMethod(" + arg + ") = " + result);

    return result;
}

这将创建一个日志文件,该文件对于查看应用程序正在执行的操作非常有用,并且它可以为写入日志的每一行添加时间戳,因此您可以查看特定方法是否需要很长时间。 使用log4net,您可以轻松更改配置以关闭注销,因此当您不需要它时,您不会支付任何性能损失。

如果您有Visual Studio Ultimate ,请尝试使用Visual Studio Profiler。 这是相当不错。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM