如何衡量 .NET 中的代码性能?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/457605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to measure code performance in .NET?
提问by Scott Marlowe
I'm doing some real quick and dirty benchmarking on a single line of C# code using DateTime:
我正在使用 DateTime 对单行 C# 代码进行一些真正快速和肮脏的基准测试:
long lStart = DateTime.Now.Ticks;
// do something
long lFinish = DateTime.Now.Ticks;
The problem is in the results:
问题在于结果:
Start Time [633679466564559902] Finish Time [633679466564559902] Start Time [633679466564569917] Finish Time [633679466564569917] Start Time [633679466564579932] Finish Time [633679466564579932]
...and so on.
...等等。
Given that the start and finish times are identical, Ticks is obviously not granular enough.
鉴于开始时间和结束时间相同,Ticks 显然不够细化。
So, how can I better measure performance?
那么,我怎样才能更好地衡量性能呢?
回答by Noldorin
The Stopwatchclass, available since .NET 2.0, is the best way to go for this. It is a very high performance counter accurate to fractions of a millisecond.
Take a look at the MSDN documentation, which is pretty clear.
Stopwatch自 .NET 2.0 起可用的类是实现此目的的最佳方式。这是一个非常高性能的计数器,精确到几分之一毫秒。看一看MSDN 文档,这很清楚。
EDIT: As previously suggested, it is also advisable to run your code a number of times in order to get a reasonable average time.
编辑:如前所述,还建议多次运行代码以获得合理的平均时间。
回答by Joachim Sauer
Execute your code repeatedly. The problem seems to be that your code executes a lot faster than the granularity of your measuring instrument. The simplest solution to this is to execute your code many, many times (thousands, maybe millions) and then calculate the average execution time.
重复执行你的代码。问题似乎是您的代码执行速度比测量仪器的粒度快得多。对此最简单的解决方案是多次执行您的代码(数千次,甚至数百万次),然后计算平均执行时间。
Edit: Also, due to the nature of current optimizing compilers (and Virtual Machines such as the CLR and the JVM) it can be very misleading to measure the execution speed of single lines of code, since the measurement can influence the speed quite a lot. A much better approach would be to profile the entire system (or at least larger blocks) and check where the bottlenecks are.
编辑:此外,由于当前优化编译器(以及 CLR 和 JVM 等虚拟机)的性质,测量单行代码的执行速度可能会非常具有误导性,因为测量会对速度产生很大影响. 更好的方法是分析整个系统(或至少更大的块)并检查瓶颈在哪里。
回答by Simon
I find these useful
我觉得这些很有用
http://accelero.codeplex.com/SourceControl/changeset/view/22633#290971http://accelero.codeplex.com/SourceControl/changeset/view/22633#290973http://accelero.codeplex.com/SourceControl/changeset/view/22633#290972
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 is a cut down copy of Stopwatch that starts when constructed and does not support restarting. It will also notify you if the current hardware does not support high resolution timing (Stopwatch swallows this problem)
TickTimer 是秒表的精简版,在构造时启动,不支持重启。如果当前硬件不支持高分辨率计时,它也会通知你(秒表吞了这个问题)
So this
所以这
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());
will output this
将输出这个
Elapsed HighResElapsedTicks 10022886
Elapsed DateTimeElapsedTicks 41896
Elapsed ElapsedMilliseconds 4.18966178849554
Start Time 11:44:58
DebugTimer is a wrapper for TickTimer that will write the result to Debug. (note: it supports the Disposable pattern)
DebugTimer 是 TickTimer 的包装器,它将结果写入 Debug。(注意:它支持 Disposable 模式)
So this
所以这
using (new DebugTimer("DoStuff"))
{
//call a method that takes some time
DoStuff();
}
will output this to the debug window
将这个输出到调试窗口
DoStuff: Total 3.6299 ms
IterationDebugTimer is for timing how long it takes to run an operation multiple times and write the result to Debug. It will also perform an initial run that is not included so as to ignore startup time. (note: it supports the Disposable pattern)
IterationDebugTimer 用于计时多次运行操作并将结果写入 Debug 所需的时间。它还将执行未包含的初始运行,以忽略启动时间。(注意:它支持 Disposable 模式)
So this
所以这
int x;
using (var iterationDebugTimer = new IterationDebugTimer("Add", 100000))
{
iterationDebugTimer.Run(() =>
{
x = 1+4;
});
}
Will output this
将输出这个
Add: Iterations 100000
Total 1.198540 ms
Single 0.000012 ms
回答by Brian Rasmussen
Just to add to what others have already said about using Stopwatch and measuring averages.
只是为了补充其他人已经说过的关于使用秒表和测量平均值的内容。
Make sure you call your method before measuring. Otherwise you will measure the time needed to JIT compile the code as well. That may skew your numbers significantly.
确保在测量之前调用您的方法。否则,您还将测量 JIT 编译代码所需的时间。这可能会严重扭曲您的数字。
Also, make sure you measure release mode code as optimizations are turned off by default for debug builds. Tuning debug code is pointless imho.
此外,请确保您测量发布模式代码,因为默认情况下调试版本的优化是关闭的。调整调试代码毫无意义恕我直言。
And make sure you're measuring what you actually want to measure. When optimizations kick in, the compiler/JIT compiler may rearrange code or remove it entirely, so you may end up measuring something a little different than intended. At least take a look at the generated code to make sure code has not been stripped.
并确保您测量的是您实际想要测量的内容。当优化开始时,编译器/JIT 编译器可能会重新排列代码或完全删除它,因此您最终可能会测量出与预期略有不同的东西。至少看看生成的代码以确保代码没有被剥离。
Depending on what you're trying to measure keep in mind, that a real system will stress the runtime differently than a typical test application. Some performance problems are related to e.g. how objects are garbage collected. These problems will typically not show up in a simple test application.
请记住,根据您要测量的内容,真实系统对运行时的压力与典型测试应用程序不同。一些性能问题与例如对象如何被垃圾收集有关。这些问题通常不会出现在简单的测试应用程序中。
Actually, the best advise is to measure real systems with real data as sandbox tests may turn out to be highly inaccurate.
实际上,最好的建议是使用真实数据来衡量真实系统,因为沙盒测试可能会非常不准确。
回答by WhTiggaW
Sample for Stopwatchclass
Stopwatch班级样本
using System.Diagnostics;
......
...
..
Stopwatch sw = new Stopwatch();
sw.Start();
//Your Code Here
sw.Stop();
Console.WriteLine("Elapsed={0}",sw.Elapsed);
回答by Evgeniy
https://andreyakinshin.gitbooks.io/performancebookdotnet/content/science/microbenchmarking.html
https://andreyakinshin.gitbooks.io/performancebookdotnet/content/science/microbenchmarking.html
https://github.com/PerfDotNet/BenchmarkDotNet
https://github.com/PerfDotNet/BenchmarkDotNet
"Indeed, microbencmarking is very hard. If an operation takes 10–100ns, the operation measurement is a big challenge. I suggest you to use BenchmarkDotNet for your benchmarks. It's a library that can help you to make an honest benchmark and get measurements with good precision. Of course, you can write own benchmark without any additional libraries. In this section, we talk about why it is probably a bad idea and what you should know before start."
“确实,微基准测试非常困难。如果一个操作需要 10-100ns,那么操作测量是一个很大的挑战。我建议你使用 BenchmarkDotNet 作为你的基准测试。它是一个可以帮助你做一个诚实的基准测试并获得测量结果的库良好的精度。当然,您可以编写自己的基准测试,而无需任何额外的库。在本节中,我们将讨论为什么这可能是一个坏主意以及您在开始之前应该了解的内容。”
回答by Otávio Décio
Use a real profiler such as dotTrace.
使用真正的分析器,例如 dotTrace。
回答by JoshBerke
You can use the Stopwatch, assuming you are using .NET 2.0 or newer.
您可以使用Stopwatch,假设您使用的是 .NET 2.0 或更新版本。
System.Diagnostics.Stopwatch.StartNew();
The Stopwatchclass also has public read-only field IsHighResolutionthat will let you know if the stopwatch is based on a high-resolution performance counter. If its not, it is based on the system timer.
本Stopwatch类也有公共只读字段IsHighResolution,可以让你知道,如果秒表是基于高分辨率的性能计数器。如果不是,则基于系统计时器。
I'm not sure what it takes for stopwatch to be based on high-resolution performance counter. There are some API calls but I figure if the stopwatch doesn't use a high resolution, then the API is probably not there.
我不确定秒表基于高分辨率性能计数器需要什么。有一些 API 调用,但我认为如果秒表不使用高分辨率,那么 API 可能不存在。
回答by Markus Olsson
See the answer to Is DateTime.Now the best way to measure a function's performance?for an explanation or read my blog post about high performance measurement
请参阅DateTime.Now 是衡量函数性能的最佳方法的答案吗?有关解释或阅读我关于高性能测量的博客文章
The problem is that DateTime has a resolution of about 15ms, it can't be more precise than that. Stopwatch, however, can.
问题是 DateTime 的分辨率约为 15 毫秒,再精确不过了。然而,秒表可以。
回答by Patrick Cuff
Here's a nice write up at the MSDN on how to Implement a Continuously Updating, High-Resolution Time Provider for Windows
这是 MSDN 上关于如何为 Windows 实现持续更新的高分辨率时间提供程序的一篇不错的文章
Here's the sample source codefor the article (C++).
这是本文的示例源代码(C++)。

