C# 衡量代码执行时间的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2072361/
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
What is the best way to measure how long code takes to execute?
提问by Edward Tanguay
I'm trying to determine which approach to removing a string is the fastest.
我正在尝试确定哪种删除字符串的方法最快。
I simply get the startand endtime and show the difference.
我只是获取开始和结束时间并显示差异。
But the results are so varied, e.g. as shown below the same method can take from 60 ms to 231 ms.
但是结果千差万别,例如,如下所示,相同的方法可能需要 60 毫秒到 231 毫秒。
What is a better method to get more accurate results?
获得更准确结果的更好方法是什么?
alt text http://www.deviantsart.com/upload/1q4t3rl.png
替代文字 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;
}
}
}
采纳答案by Scott Anderson
You should use System.Diagnostics.Stopwatch, and you might want to consider a large sample. For example, repeat this test something like 10,000 times and average the results. If you think about it scientifically, it makes sense. The larger the sample, the better. You can weed out a lot of edge cases this way and really see what the core performance is like.
您应该使用System.Diagnostics.Stopwatch,并且您可能需要考虑一个大样本。例如,重复此测试 10,000 次并取平均结果。如果从科学的角度考虑,这是有道理的。样本越大越好。您可以通过这种方式清除很多边缘情况,并真正了解核心性能。
Another thing to consider is that JIT compilation and object creation can definitely skew your results, so make sure that you start and stop your Stopwatch at the appropriate times, and call the methods you want to test at least once before you begin your tests. Try to segregate just the parts you want to test from the rest of your code as much as possible.
另一件要考虑的事情是,JIT 编译和对象创建肯定会扭曲您的结果,因此请确保在适当的时间启动和停止秒表,并在开始测试之前至少调用一次要测试的方法。尝试尽可能地将您想要测试的部分与代码的其余部分分开。
回答by Jo?o Angelo
You can use the Stopwatchclass.
您可以使用秒表类。
The Stopwatch measures elapsed time by counting timer ticks in the underlying timer mechanism. If the installed hardware and operating system support a high-resolution performance counter, then the Stopwatch class uses that counter to measure elapsed time.
秒表通过计算底层计时器机制中的计时器滴答来测量经过的时间。如果安装的硬件和操作系统支持高分辨率性能计数器,则 Stopwatch 类使用该计数器来测量经过的时间。
var sw = new Stopwatch();
sw.Start();
// ...
sw.Stop();
回答by Extrakun
You may have to apply some statistical techniques here to iron out the variance. Try running the same piece of code 1000 times and then take the average time, and compare that. Simulations usually employ some sort of methods to 'clean up' the numbers, and this is one of those.
您可能需要在此处应用一些统计技术来消除差异。尝试运行同一段代码 1000 次,然后取平均时间,然后进行比较。模拟通常采用某种方法来“清理”数字,这就是其中之一。
回答by Justin Niessner
If you're only worried about testing it in your own code...use a System.Diagnostics.Stopwatch
如果你只是担心在你自己的代码中测试它......使用 System.Diagnostics.Stopwatch
I usually prefer breaking this kind of thing out of my code and using a true Profiler like RedGate's Performance Profiler
我通常更喜欢从我的代码中打破这种东西并使用真正的 Profiler,比如RedGate 的 Performance Profiler
回答by jason
Three simple notes:
三个简单的笔记:
Don't profile your code on the same input one million times. Try to find your expected distribution of inputs and profile on that. That is profile on real-world input, not laboratory input.
Run the
Clean
method once before entering the profiling loop to eliminate JITting time. Sometimes this is important.
不要在同一输入上分析您的代码一百万次。尝试找到您预期的输入分布和配置文件。那是真实世界输入的概况,而不是实验室输入。
Clean
在进入分析循环之前运行一次该方法以消除 JITting 时间。有时这很重要。
Of these, notes 1. and 2. are by far the most important.
其中,注释 1. 和 2. 是迄今为止最重要的。
Your profiling results are meaningless if you are not using a high-resolution timer. Note that we don't time Usain Boltusing a water clock.
如果您不使用高分辨率计时器,您的分析结果将毫无意义。请注意,我们不使用水钟为Usain Bolt计时。
Your profiling results are meaningless if you are not testing on real-world input. Note that crash tests crash cars head on into other cars at 35 MPH, not into walls made of marshmellows at 5 MPH.
如果您不是在实际输入上进行测试,那么您的分析结果将毫无意义。请注意,碰撞测试以 35 MPH 的速度撞到其他汽车,而不是撞到由棉花糖制成的墙壁,速度为 5 MPH。
Thus:
因此:
// 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);
One complex note:
一个复杂的注释:
If you really need to do profiling, get a profiler like ANTS.
如果您确实需要进行分析,请使用ANTS 之类的分析器。
回答by Joey
Generally: Don't look at the wallclock time but the CPU time consumed by your process to determine how long it ran. Especially for things that are just computation this is much more reliable because it will be unaffected by other processes running at the same time.
通常:不要查看挂钟时间,而是查看进程消耗的 CPU 时间来确定它运行了多长时间。特别是对于只是计算的事情,这更加可靠,因为它不会受到同时运行的其他进程的影响。
回答by High Performance Mark
The trouble with all the clock-based approaches is that you are never quite certain what you are timing. You might, whether you realise it or not, include in your timing:
所有基于时钟的方法的问题在于,您永远无法确定自己正在计时。无论您是否意识到,您都可以在您的时间安排中包括:
- delays while the o/s pre-empts your processor;
- context-switching
- stalls while the program waits for data;
- and much much more.
- o/s 抢占您的处理器时出现延迟;
- 上下文切换
- 在程序等待数据时停止;
- 还有更多。
I'm not saying that all of these apply to this particular timing but to timings in general. So you should supplement any timing you do with some consideration of how many basic operations your alternative codes execute -- some considerations of complexity not ignoring (as we usually do) the constant terms.
我并不是说所有这些都适用于这个特定的时间,而是一般的时间。因此,您应该考虑您的替代代码执行多少基本操作来补充您所做的任何时间 - 一些复杂性的考虑而不是忽略(正如我们通常所做的那样)常数项。
In your particular case you should aim to time much longer executions; when your times are sub-second the o/s is extremely likely to mess you around. So run 10^6 iterations and use the average over enough runs to give you a meaningful calculation of average and variance. And make sure, if you take this approach, that you don't inadvertently speed up the second trial by having data already loaded after the end of the first trial. You have to make sure that each of the 10^6 trials does exactly what the 1st trial does.
在您的特定情况下,您应该瞄准更长的执行时间;当您的时间为亚秒时,o/s 极有可能让您感到困惑。因此,运行 10^6 次迭代并在足够多的运行中使用平均值来为您提供有意义的平均值和方差计算。并确保,如果您采用这种方法,您不会因为在第一次试验结束后已经加载数据而无意中加快了第二次试验的速度。您必须确保 10^6 次试验中的每一次都与第 1 次试验完全相同。
Have fun
玩得开心
Mark
标记
回答by Sam Harwell
I'll have to recommend the highlyprofiler included in Visual Studio Team Suite or Development Edition(or the upcoming Visual Studio 2010 Premium or Ultimateis even better) as the best way. It is highly configurable, extremely powerful, dead simple to use, very fast, and works with both native and managed code. I'm not familiar with the workflow of ANTS, but that appears to be another option. Without a doubt using a profiler is the onlyoption for a developer that is concerned with their application's performance. There is no substitute, and you really can't take any commercial developer working on performance that would pass up a profiler seriously.
我不得不推荐包含在Visual Studio Team Suite 或 Development Edition(或者即将推出的Visual Studio 2010 Premium 或 Ultimate更好)中的高度分析器作为最好的方法。它是高度可配置的,非常强大,使用起来非常简单,非常快,并且可以与本机和托管代码一起使用。我不熟悉ANTS的工作流程,但这似乎是另一种选择。毫无疑问,对于关注其应用程序性能的开发人员来说,使用分析器是唯一的选择。没有替代品,您真的不能接受任何致力于性能的商业开发人员会认真地忽略分析器。
However, if you are interested in measurements for one of the following, you may not have access such a profiler, in which case the Stopwatch class can form a basis for your measurement technique:
但是,如果您对以下一项的测量感兴趣,您可能无法访问这样的分析器,在这种情况下,秒表类可以构成您的测量技术的基础:
- A student or hobbyist interested in performance of their projects (a commercial profiler may be out of reach for financial reasons)
- In a publicly released application, you may want to time sections of code that execute on the UI thread and report statistics to may sure the operations never cause noticeable delays for any of your users. The Office team used a method like this with enormous success (Outlook 2007 SP2 anyone?), and I know the Visual Studio team has this code in at least the 2010 release.
- 对他们的项目表现感兴趣的学生或业余爱好者(出于经济原因,商业分析器可能遥不可及)
- 在公开发布的应用程序中,您可能希望对在 UI 线程上执行的代码段进行计时并报告统计信息,以确保这些操作不会对您的任何用户造成明显的延迟。Office 团队使用这样的方法取得了巨大的成功(有人使用 Outlook 2007 SP2 吗?),而且我知道 Visual Studio 团队至少在 2010 版本中有此代码。
回答by Pavel Vladov
There's a lot of activity going on under the hood of the OS, which is very likely to mess up your time measurements. In order to improve the accuracy of the measured times you should execute the tests multiple times and remove the lowest and the greatest times from the final results. This approach will exclude most of the external factors that may influence your code's execution time and will serve you well in most cases. The Stopwatchclass is used to measure time as it is much more accurate than using DateTime.
在操作系统的引擎盖下有很多活动正在进行,这很可能会扰乱您的时间测量。为了提高测量时间的准确性,您应该多次执行测试并从最终结果中删除最低和最高时间。这种方法将排除可能影响代码执行时间的大多数外部因素,并且在大多数情况下都能很好地为您服务。该秒表类是用来测量时间,因为它比使用更准确的日期时间。
You can easily make a test class to automate this. I have published one such class in my blog. It can compare the performance of two C# code fragments/algorithms. All you have to do is to override the Method1 and Method2 methods putting there the code fragments you want to test and use the test class like this:
您可以轻松制作一个测试类来自动执行此操作。我在我的博客中发布了一个这样的课程。它可以比较两个 C# 代码片段/算法的性能。您所要做的就是覆盖 Method1 和 Method2 方法,将要测试的代码片段放在那里,并像这样使用测试类:
Test test = new CustomTest();
Console.WriteLine("\n==============================");
Console.WriteLine(test.Execute());
Console.WriteLine("==============================\n");
回答by Krisi Suci
You can also use log4net, simply add log.Info("Test") where you wanna track stuff and you will find all your info and the time that line was executed in a txt file, for example: 2018-12-13 10:02:16,704 [9] INFO Hms.Domain.Concrete.RoomsRepository [(null)] - Test
Read more about it here: https://www.infoworld.com/article/3120909/application-development/how-to-work-with-log4net-in-c.html
您也可以使用 log4net,只需在要跟踪内容的位置添加 log.Info("Test"),您就会在 txt 文件中找到所有信息和该行执行的时间,例如:2018-12-13 10:02:16,704 [9] INFO Hms.Domain.Concrete.RoomsRepository [(null)] - Test
在此处阅读更多信息:https ://www.infoworld.com/article/3120909/application-development/how-to-work-with-log4net-in-c.html