计算方法的执行时间

Mah*_*ari 494 .net c# io timer stopwatch

可能重复:
如何测量函数运行的时间?

我有一个I/O计时方法,可以将数据从一个位置复制到另一个位置.什么是计算执行时间的最佳和最实际的方法?ThreadTimerStopwatch?还有其他方法吗?我想要最精确的一个,尽可能简短.

Dar*_*rov 1038

Stopwatch 是为此目的而设计的,是衡量.NET中时间执行的最佳方法之一.

var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Run Code Online (Sandbox Code Playgroud)

不要使用DateTime来测量.NET中的时间执行.


更新:

正如@ series0ne在评论部分所指出的:如果您想要对某些代码的执行进行真正精确的测量,则必须使用内置于操作系统中的性能计数器.在以下的答案必须包含一个很好的概述.

  • @DarinDimitrov - 秒表不完全准确吗?请记住,.NET背景噪声(例如JITing)会导致执行时间不同.因此,实际上,为了准确测量,OP应该使用性能分析器. (13认同)
  • @DarinDimitrov,我最近接受了一位非常熟练的高级开发人员的采访.他向我指出,使用DateTimes实际上比使用StopWatch更准确.他说这样做的原因是.NET中的秒表没有考虑CPU亲和性,因此,如果你的线程从一个核心移动到另一个核心,StopWatch不会考虑其他核心的执行时间; 只有线程开始执行的那个.你对这个有什么看法? (7认同)
  • @ series0ne,非常好点.我会更新我的回答,以包括您的宝贵意见. (3认同)
  • 确切地说,这个案例怎么样:我有一个foreach循环,它有一个`ThreadPool.QueueUserWorkItem(委托{CopyFiles(folder,dest);}); `里面,但秒表在一切完成之前停止. (2认同)
  • @ series0ne,高级开发人员告诉你的关于秒表和DateTime的内容是绝对正确的.除了使用DateTime,您没有足够的准确性.问题是.NET中没有这样的类允许你使用所有这些功能. (2认同)

ser*_*0ne 72

从个人的经验来看,System.Diagnostics.Stopwatch类可以用来测量方法的执行时间,但是当心:这是不完全准确!

请考虑以下示例:

Stopwatch sw;

for(int index = 0; index < 10; index++)
{
    sw = Stopwatch.StartNew();
    DoSomething();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

sw.Stop();
Run Code Online (Sandbox Code Playgroud)

示例结果

132ms
4ms
3ms
3ms
2ms
3ms
34ms
2ms
1ms
1ms
Run Code Online (Sandbox Code Playgroud)

现在你想知道; "那么为什么第一次需要132毫秒,其余时间显着减少?"

答案是Stopwatch不能补偿.NET中的"背景噪音"活动,例如JITing.因此,第一次运行方法时,.NET JIT首先运行它.执行此操作所需的时间将添加到执行时.同样,其他因素也会导致执行时间发生变化.

您应该真正寻求绝对准确性的是性能分析!

看看以下内容:

RedGate ANTS Performance Profiler是一种商业产品,但可以产生非常准确的结果.- 使用.NET分析提高应用程序的性能

这是关于分析的StackOverflow文章: - 什么是一些好的.NET Profilers?

我还写了一篇关于使用秒表的性能分析的文章,你可能想看一下 - 在.NET中进行性能分析

  • 我不确定为什么这是*不准确*的例子.秒表准确地测量第一次通话的总成本,这肯定是与将要运行此代码的客户相关的.他们不关心132毫秒是否为方法执行或抖动收费,他们关心的是经过的总时间. (38认同)
  • @mahditahsildari没问题.很高兴我能帮助你!:-) (2认同)
  • @series0ne 如果您关心循环的性能,那么测量循环的性能。不要简单地假设做某事 *n* 次意味着它会比执行一次慢 *n* 倍。 (2认同)
  • 首先,由于StopWatch永远不会在循环中重置,因此代码示例应产生数量不断增加的输出。“应该”是指(我检查了)。因此您的输出与代码不匹配。其次,当我更正代码以在循环中执行“停止/写入/重置/启动”时,第一次测量与其余测量相同。我的猜测是您的DoSomething在第一次运行时会做更长的时间。JIT可能是原因,也可能不是,但并不是说Stopwatch正在影响测量。因此-1。 (2认同)
  • ILIA BROUDNO是绝对正确的,我得到了相同的结果。@ series0ne,循环中有一个Console.WriteLine,到目前为止已写入ms;因为您只在循环结束后才停止计时,所以每次循环都会随着时间的增加而增加,因此随着执行时间的累积,我们应该会看到类似3、6、10、12、15等的信息。 (2认同)

Son*_*nül 28

StopWatch 课程寻找最佳解决方案.

Stopwatch sw = Stopwatch.StartNew();
DoSomeWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
Run Code Online (Sandbox Code Playgroud)

它还有一个名为的静态字段Stopwatch.IsHighResolution.当然,这是硬件和操作系统问题.

指示计时器是否基于高分辨率性能计数器.


Jef*_*ter 17

如果您有兴趣了解性能,最好的答案是使用分析器.

否则,System.Diagnostics.StopWatch提供高分辨率计时器.


Bri*_*new 7

StopWatch将使用高分辨率计数器

秒表通过计算基础计时器机制中的计时器滴答来测量经过的时间.如果安装的硬件和操作系统支持高分辨率性能计数器,则Stopwatch类使用该计数器来测量经过的时间.否则,Stopwatch类使用系统计时器来测量经过的时间.使用Frequency和IsHighResolution字段确定秒表计时实施的精度和分辨率.

如果您正在测量IO,那么您的数据可能会受到外部事件的影响,我会非常担心.准确性(如上所述).相反,我会进行一系列测量,并考虑这些数字的平均值和分布.


小智 7

您还可以使用“获取自系统启动以来经过的毫秒数”。

System.Environment.TickCount
Run Code Online (Sandbox Code Playgroud)

例如

static void method1()
{
    for (int i = 1; i <= 100; i++)
    {
        Console.WriteLine("Test1 " + i);
    }
}
static void Main(string[] args)
{
    var startTime = Environment.TickCount;
    method1();
    var endTime = Environment.TickCount;
    Console.WriteLine("RunTime " + (endTime - startTime));
}
Run Code Online (Sandbox Code Playgroud)


小智 5

遵循此Microsoft Doc

using System;
using System.Diagnostics;
using System.Threading;
class Program
{
    static void Main(string[] args)
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        Thread.Sleep(10000);
        stopWatch.Stop();
        // Get the elapsed time as a TimeSpan value.
        TimeSpan ts = stopWatch.Elapsed;

        // Format and display the TimeSpan value.
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours, ts.Minutes, ts.Seconds,
            ts.Milliseconds / 10);
        Console.WriteLine("RunTime " + elapsedTime);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出: RunTime 00:00:09.94