我正在使用DateTime对一行C#代码进行一些真正的快速和脏的基准测试:
long lStart = DateTime.Now.Ticks; // do something long lFinish = DateTime.Now.Ticks;
问题在于结果:
Start Time [633679466564559902] Finish Time [633679466564559902] Start Time [633679466564569917] Finish Time [633679466564569917] Start Time [633679466564579932] Finish Time [633679466564579932]
...等等.
鉴于开始和结束时间相同,Ticks显然不够精细.
那么,我怎样才能更好地衡量绩效呢?
Stopwatch
从.NET 2.0开始提供的这个类是最好的方法.它是一个非常高性能的计数器,精确到几毫秒.看看MSDN文档,这很清楚.
编辑:如前所述,建议多次运行代码以获得合理的平均时间.
重复执行您的代码.问题似乎是您的代码执行速度比测量仪器的粒度快得多.对此最简单的解决方案是执行许多次(数千次,数百万次)代码,然后计算平均执行时间.
编辑:此外,由于当前优化编译器(以及CLR和JVM等虚拟机)的性质,测量单行代码的执行速度可能会非常误导,因为测量可能会对速度产生很大的影响.更好的方法是分析整个系统(或至少更大的块)并检查瓶颈在哪里.
我觉得这些很有用
http://accelero.codeplex.com/SourceControl/changeset/view/22633#290971 http://accelero.codeplex.com/SourceControl/changeset/view/22633#290973 http://accelero.codeplex.com/SourceControl/变更/视图/ 22633#290972
TickTimer是Stopwatch的缩减副本,在构建时启动并且不支持重新启动.如果当前硬件不支持高分辨率计时,它也会通知您(秒表吞下此问题)
所以这
var tickTimer = new TickTimer(); //call a method that takes some time DoStuff(); tickTimer.Stop(); Debug.WriteLine("Elapsed HighResElapsedTicks " + tickTimer.HighResElapsedTicks); Debug.WriteLine("Elapsed DateTimeElapsedTicks " + tickTimer.DateTimeElapsedTicks); Debug.WriteLine("Elapsed ElapsedMilliseconds " + tickTimer.ElapsedMilliseconds); Debug.WriteLine("Start Time " + new DateTime(tickTimer.DateTimeUtcStartTicks).ToLocalTime().ToLongTimeString());
会输出这个
Elapsed HighResElapsedTicks 10022886 Elapsed DateTimeElapsedTicks 41896 Elapsed ElapsedMilliseconds 4.18966178849554 Start Time 11:44:58
DebugTimer是TickTimer的包装器,它将结果写入Debug.(注意:它支持一次性模式)
所以这
using (new DebugTimer("DoStuff")) { //call a method that takes some time DoStuff(); }
将它输出到调试窗口
DoStuff: Total 3.6299 ms
IterationDebugTimer用于计算多次运行操作并将结果写入Debug所需的时间.它还将执行未包含的初始运行,以忽略启动时间.(注意:它支持一次性模式)
所以这
int x; using (var iterationDebugTimer = new IterationDebugTimer("Add", 100000)) { iterationDebugTimer.Run(() => { x = 1+4; }); }
会输出这个
Add: Iterations 100000 Total 1.198540 ms Single 0.000012 ms
只是添加其他人已经说过的关于使用秒表和测量平均值的内容.
确保在测量前调用您的方法.否则,您将测量JIT编译代码所需的时间.这可能会显着扭曲您的数字.
此外,请确保测量发布模式代码,因为默认情况下调试版本的优化已关闭.调整调试代码是毫无意义的.
并确保您正在测量您实际想要测量的内容.当优化启动时,编译器/ JIT编译器可能会重新排列代码或将其完全删除,因此您最终可能会测量与预期稍有不同的内容.至少看看生成的代码,以确保代码没有被剥离.
根据您要测量的内容,请注意,真实系统会比典型的测试应用程序更不同于运行时.一些性能问题与例如垃圾收集对象有关.这些问题通常不会出现在简单的测试应用程序中.
实际上,最好的建议是使用真实数据来测量真实系统,因为沙箱测试可能会变得非常不准确.