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

我试图确定删除string的方法是最快的

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

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

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

替代文字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; } } } 

你应该使用System.Diagnostics.Stopwatch ,你可能想考虑一个大样本。 例如,重复这个testing大约10000次,并取平均值。 如果你科学的思考,这是有道理的。 样本越大越好。 你可以通过这种方式去除很多边缘情况,并且真正看到核心性能是什么样的。

另一件要考虑的事情是,JIT编译和对象创build肯定会歪曲你的结果,所以要确保你在适当的时候启动和停止你的秒表,并且在你开始testing之前至less调用一次你想testing的方法。 尝试尽可能地从您的代码中分离出您想要testing的部分。

三个简单的说明:

  1. 使用System.Diagnostics.Stopwatch 。

  2. 不要在同一个input上分析你的代码一百万次。 尝试find你的预期分布的input和configuration文件。 这是真实世界的input,而不是实验室的input。

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

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

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

如果您没有对真实世界的input进行testing,那么分析结果就毫无意义。 请注意,碰撞试验会使车辆以35 MPH的速度撞向其他车辆,而不是以5 MPH的速度撞击到沼泽地的墙壁上。

从而:

 // expectedInput is string[1000000] // populate expectedInput with real-world input Clean(expectedInput[0]); Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 1000000; i++) { string t = Clean(expectedInput[i]); } sw.Stop(); Console.WriteLine(sw.Elapsed); 

一个复杂的说明:

如果你真的需要分析,请获得一个类似ANTS的分析器。

您可以使用秒表类。

秒表通过计数基础定时器机制中的计时器滴答来测量已用时间。 如果安装的硬件和操作系统支持高分辨率性能计数器,则秒表类使用该计数器来测量已用时间。

 var sw = new Stopwatch(); sw.Start(); // ... sw.Stop(); 

如果您只是担心在自己的代码中进行testing,请使用System.Diagnostics.Stopwatch

我通常更喜欢从我的代码中打破这种东西,并使用像RedGate的性能分析器这样的真实的Profiler

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

你可以很容易地做一个testing课程来自动化这个。 我在博客上发表了一个这样的课 。 它可以比较两个C#代码片段/algorithm的性能。 所有你需要做的就是重写Method1和Method2方法,在那里放置你想testing的代码片段,并像这样使用testing类:

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

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

一般来说:不要看挂钟时间,而要看你的进程消耗的CPU时间,以确定它运行的时间。 特别是对于只是计算的东西来说,这更可靠,因为它不会受到同时运行的其他进程的影响。

所有基于时钟的方法的麻烦在于,你不能确定你正在计时的是什么。 不pipe你是否意识到,你可能都会在你的时间内包括:

  • 在o / s抢占你的处理器时延迟;
  • 上下文切换
  • 在程序等待数据时停止;
  • 还有更多。

我并不是说所有这些都适用于这个特定的时间,而是适用于一般的时间。 所以,你应该补充任何时间你考虑一下你的替代代码执行多less基本操作 – 一些复杂性的考虑不会忽略(像我们通常那样)常数项。

在你的具体情况下,你应该瞄准时间更长的处决时间; 当你的时间是亚秒的时候,你很可能会把你搅乱。 因此,运行10 ^ 6次迭代,并使用足够的运行平均值给你一个有意义的平均值和方差的计算。 如果采取这种方法,确保在第一次试用结束后数据已经加载,而不会无意中加速第二次试用。 你必须确保10 ^ 6试验中的每一个都完全符合第一次试验的要求。

玩的开心

标记

我将不得不推荐包含在Visual Studio Team Suite或Development Edition (或即将发布的Visual Studio 2010 Premium或Ultimate )中的高性能分析器作为最佳方式。 它是高度可configuration的,function非常强大,使用起来非常简单,速度非常快,可以同时使用本地代码和托pipe代码。 我不熟悉ANTS的工作stream程,但似乎是另一种select。 毫无疑问,使用分析器是开发人员关注应用程序性能的唯一select。 没有替代品,你真的不能接受任何商业开发人员的工作performance,认真传递一个分析器。

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

  • 对他们的项目performance感兴趣的学生或业余爱好者(由于经济原因,商业分析师可能遥不可及)
  • 在公开发布的应用程序中,您可能需要对UI线程中执行的代码段进行计时,并报告统计信息,以确保操作不会导致任何用户明显的延迟。 Office团队使用了这样的方法取得了巨大的成功(Outlook 2007 SP2中的任何人?),而且我知道Visual Studio团队至less在2010版本中包含此代码。