衡量代码执行时间的最佳方法是什么?

时间:2010-01-15 14:49:52

标签: c# performance

我正在尝试确定删除字符串的方法是最快

我只是得到开始结束时间并显示差异。

但结果如此变化,例如如下图所示,同样的方法可以从60毫秒到231毫秒。

获得更准确结果的更好方法是什么?

alt text http://www.deviantsart.com/upload/1q4t3rl.png

using System;
using System.Collections;
using System.Collections.Generic;

namespace TestRemoveFast
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int j = 0; j < 10; j++)
            {
                string newone = "";
                List<string> tests = new List<string>();
                for (int i = 0; i < 100000; i++)
                {
                    tests.Add("{http://company.com/Services/Types}ModifiedAt");
                }

                DateTime start = DateTime.Now;
                foreach (var test in tests)
                {
                    //newone = ((System.Xml.Linq.XName)"{http://company.com/Services/Types}ModifiedAt").LocalName;
                    newone = Clean(test);
                }

                Console.WriteLine(newone);
                DateTime end = DateTime.Now;
                TimeSpan duration = end - start;
                Console.WriteLine(duration.ToString());
            }

            Console.ReadLine();
        }

        static string Clean(string line)
        {
            int pos = line.LastIndexOf('}');
            if (pos > 0)
                return line.Substring(pos + 1, line.Length - pos - 1);
                //return line.Substring(pos + 1);
            else
                return line;
        }
    }
}

10 个答案:

答案 0 :(得分:46)

您应该使用System.Diagnostics.Stopwatch,并且可能需要考虑大样本。例如,重复此测试类似10,000次并平均结果。如果你从科学角度思考它,那就有道理了。样本越大越好。您可以通过这种方式清除大量边缘情况,并真正了解核心性能是什么样的。

另一件需要考虑的事情是JIT编译和对象创建肯定会使结果产生偏差,因此请确保在适当的时间启动和停止秒表,并在开始之前至少调用一次要测试的方法试验。尝试尽可能地将您要测试的部分与其余代码隔离开来。

答案 1 :(得分:36)

三个简单的注释:

  1. 使用System.Diagnostics.Stopwatch

  2. 不要在相同的输入上分析您的代码一百万次。尝试找到您的输入和配置文件的预期分布。这是对实际输入的描述,而不是实验室输入。

  3. 在进入性能分析循环之前运行Clean方法一次以消除JITting时间。有时这很重要。

  4. 其中,注释1.和2.是迄今为止最重要的。

    如果您不使用高分辨率计时器,则您的分析结果毫无意义。请注意,我们不会使用Usain Bolt时间water clock

    如果您没有测试真实世界的输入,那么您的分析结果毫无意义。请注意,碰撞测试会使汽车以35英里/小时的速度撞向其他车辆,而不是以5英里/小时的速度撞到由marshmellows制成的墙壁上。

    因此:

    // expectedInput is string[1000000]
    // populate expectedInput with real-world input
    Clean(expectedInput[0]);
    Stopwatch sw = new Stopwatch();
    sw.Restart();          //So you dont have to call sw.Reset()
    for (int i = 0; i < 1000000; i++) {
        string t = Clean(expectedInput[i]);
    }
    sw.Stop();
    Console.WriteLine(sw.Elapsed);
    

    一个复杂的说明:

    如果您确实需要进行性能分析,请使用ANTS等分析器。

答案 2 :(得分:6)

您可以使用Stopwatch类。

  

秒表测量经过的时间   计算计时器滴答在底层   计时器机制。如果安装   硬件和操作系统支持   一个高分辨率的性能计数器,   然后秒表类使用它   用来衡量经过的时间。

var sw = new Stopwatch();

sw.Start();
// ...
sw.Stop();

答案 3 :(得分:3)

如果您只是担心在自己的代码中测试它...请使用System.Diagnostics.Stopwatch

我通常更喜欢从我的代码中删除此类内容并使用真正的Profiler,如RedGate's Performance Profiler

答案 4 :(得分:2)

在操作系统的引擎下会有很多活动,这很可能会让你的时间测量变得混乱。为了提高测量时间的准确性,您应该多次执行测试并从最终结果中删除最低和最高时间。这种方法将排除可能影响代码执行时间的大多数外部因素,并且在大多数情况下都能很好地为您服务。 Stopwatch类用于衡量时间,因为它比使用DateTime更准确。

您可以轻松地创建一个测试类来自动执行此操作。我已发布one such class in my blog。它可以比较两个C#代码片段/算法的性能。您所要做的就是覆盖Method1和Method2方法,将要测试的代码片段放在那里并使用如下测试类:

Test test = new CustomTest();
Console.WriteLine("\n==============================");
Console.WriteLine(test.Execute());
Console.WriteLine("==============================\n");

答案 5 :(得分:0)

您可能必须在此处应用一些统计技术来消除差异。尝试运行相同的代码1000次,然后取平均时间,并进行比较。模拟通常采用某种方法来“清理”数字,这就是其中之一。

答案 6 :(得分:0)

通常:不要查看wallclock时间,而是查看进程消耗的CPU时间以确定其运行时间。特别是对于那些只是计算的东西,它更加可靠,因为它不会受到同时运行的其他进程的影响。

答案 7 :(得分:0)

所有基于时钟的方法的问题在于,您永远不能确定您的计时。无论你是否意识到,你可能会在你的时间安排中包括:

  • 在o / s抢先处理器时延迟;
  • 上下文切换
  • 在程序等待数据时停止;
  • 以及更多。

我并不是说所有这些都适用于这个特定的时间,而是适用于一般的时间。所以你应该考虑你的替代代码执行了多少基本操作来补充你做的任何时间 - 复杂性的一些考虑因素而不是忽略(通常我们通常做的)常数术语。

在你的特殊情况下,你应该瞄准更长时间的执行时间;当你的时间低于秒时,o / s极有可能让你四处乱窜。因此,运行10 ^ 6次迭代并使用平均值足够的运行来为您提供有意义的平均值和方差计算。并确保,如果采用这种方法,在第一次试验结束后,通过使数据已经加载,您不会无意中加速第二次试验。您必须确保10 ^ 6个试验中的每一个都完全符合第一次试验的要求。

玩得开心

标记

答案 8 :(得分:0)

我必须推荐Visual Studio Team Suite or Development Edition中包含的高度分析器(或即将推出的Visual Studio 2010 Premium or Ultimate更好)作为最佳方式。它具有高度可配置性,功能强大,易于使用,速度非常快,并且可以使用本机代码和托管代码。我不熟悉ANTS的工作流程,但这似乎是另一种选择。毫无疑问,对于关注其应用程序性能的开发人员而言,使用分析器是选项。 没有替代品,你真的不能让任何商业开发人员在性能上认真对待分析器。

但是,如果您对以下某项测量感兴趣,则可能无法访问此类分析器,在这种情况下,秒表类可以构成您的测量技术的基础:

  • 对项目执行感兴趣的学生或业余爱好者(由于经济原因,商业资料管理器可能无法访问)
  • 在公开发布的应用程序中,您可能希望计算在UI线程上执行的代码段并报告统计信息,以确保操作不会对任何用户造成明显的延迟。 Office团队使用这样的方法取得了巨大的成功(Outlook 2007 SP2有人吗?),我知道Visual Studio团队至少在2010版本中有这个代码。

答案 9 :(得分:-1)

您还可以使用log4net,只需在要跟踪内容的地方添加log.Info(“ Test”),即可在txt文件中找到所有信息以及执行该行的时间,例如:{{1} }在此处了解更多信息:https://www.infoworld.com/article/3120909/application-development/how-to-work-with-log4net-in-c.html