C# 是DateTime。现在测量函数的最佳方法是';她的表现如何?

C# 是DateTime。现在测量函数的最佳方法是';她的表现如何?,c#,.net,performance,datetime,timer,C#,.net,Performance,Datetime,Timer,我需要找到一个瓶颈,需要尽可能准确地测量时间 下面的代码片段是度量性能的最佳方法吗 DateTime startTime = DateTime.Now; // Some execution process DateTime endTime = DateTime.Now; TimeSpan totalTimeTaken = endTime.Subtract(startTime); 功能会更好(精度更高)。不过,我也建议只下载一个流行的评测器(也是我使用最多的评测器……DotTrace的免费试

我需要找到一个瓶颈,需要尽可能准确地测量时间

下面的代码片段是度量性能的最佳方法吗

DateTime startTime = DateTime.Now;

// Some execution process

DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
功能会更好(精度更高)。不过,我也建议只下载一个流行的评测器(也是我使用最多的评测器……DotTrace的免费试用版功能齐全,不会像其他一些评测器那样唠叨)。

不,不是。使用(在
系统诊断中)

秒表自动检查是否存在高精度计时器

值得一提的是,
DateTime.Now
通常比
DateTime.UtcNow
慢一点,这是因为必须对时区等进行处理

DateTime.UtcNow的分辨率通常为15毫秒。请参阅关于
DateTime.Now
precision以获得一个很好的摘要


有趣的琐事:如果您的硬件不支持高频计数器,秒表会回到
DateTime.UtcNow
。通过查看静态字段,可以检查秒表是否使用硬件来实现高精度。

使用System.Diagnostics.Stopwatch类

Stopwatch sw = new Stopwatch();
sw.Start();

// Do some code.

sw.Stop();

// sw.ElapsedMilliseconds = the time your "do some code" took.

我很少做这种性能检查(我倾向于认为“这很慢,让它更快”),所以我几乎总是这样做

谷歌确实透露了很多用于性能检查的资源/文章

许多人提到使用pinvoke获取性能信息。我研究的很多资料都只提到使用perfmon

编辑: 我看过秒表的谈话。。美好的我学到了一些东西:)


如果你想要快速而肮脏的东西,我建议你用秒表来代替,以获得更高的精确度

Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();

Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);
P>可选的,如果你需要更复杂的东西,你应该考虑使用第三方分析器,例如./P>

@ /P> 仅供参考,.NET Timer类不用于诊断,它以预设间隔生成事件,如下所示(从):

所以,这并不能帮助你知道某件事花了多长时间,只是一段时间过去了


计时器也在System.Windows.Forms中作为控件公开。。。您可以在VS05/VS08中的designer工具箱中找到它,与秒表一样,它要好得多

关于绩效衡量,您还应该检查您的“//Some Execution Process”是否是一个非常短的过程

还要记住,第一次运行“//Some Execution Process”可能比后续运行慢得多


我通常通过在一个循环中运行1000次或1000000次来测试一个方法,我得到的数据比运行一次要准确得多。

将基准测试代码推送到实用程序类/方法中非常有用。
StopWatch
类不需要在出现错误时进行
处理
停止
。因此,对某些操作计时的最简单代码是

调用代码示例

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Did action in {0} ms.”, time);
}
public void Execute(Action action)
{
    var time = action.Benchmark()
    log.DebugFormat(“Did action in {0} ms.”, time);
}
这是扩展方法版本

public static class Extensions
{
    public static long Benchmark(this Action action)
    {
        return With.Benchmark(action);
    }
}
和示例调用代码

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Did action in {0} ms.”, time);
}
public void Execute(Action action)
{
    var time = action.Benchmark()
    log.DebugFormat(“Did action in {0} ms.”, time);
}

我刚在Vance Morrison的博客上找到一篇文章,内容是关于他写的,这篇文章使使用秒表变得更容易,并且做了一些简单的事情。

Visual Studio Team System的一些功能可能有助于解决此问题。基本上,您可以编写单元测试,并将它们混合在不同的场景中,作为压力测试或负载测试的一部分针对您的软件运行。这可能有助于确定对应用程序性能影响最大的代码区域


微软的模式和实践小组提供了一些指导。

这些都是测量时间的好方法,但这只是一种非常间接的方法来发现瓶颈

在线程中找到bottneck最直接的方法是让它运行,当它执行任何让您等待的操作时,使用暂停或断开键来停止它。这样做几次。如果瓶颈占用了X%的时间,则X%是您在每个快照的act中捕获瓶颈的概率


这是正确的方法:

using System;
using System.Diagnostics;

class Program
{
    public static void Main()
    {
        Stopwatch stopWatch = Stopwatch.StartNew();

            // some other code

        stopWatch.Stop();

        // this not correct to get full timer resolution
        Console.WriteLine("{0} ms", stopWatch.ElapsedMilliseconds);

        // Correct way to get accurate high precision timing
        Console.WriteLine("{0} ms", stopWatch.Elapsed.TotalMilliseconds);
    }
}
有关更多信息,请浏览。

表示,首先需要比较三种备选方案,
秒表
日期时间。现在
日期时间.UtcNow

它还表明,在某些情况下(当性能计数器不存在时),秒表正在使用DateTime.UtcNow+一些额外的处理。因此,很明显,在这种情况下,DateTime.UtcNow是最好的选择(因为其他人使用它+一些处理)

然而,事实证明,计数器几乎总是存在的——请参阅

这是一个性能图。请注意UtcNow的性能成本与备选方案相比有多低:

X轴是样本数据大小,Y轴是示例的相对时间


秒表
更擅长的一点是它提供了更高分辨率的时间测量。另一个原因是它的OO特性。但是,围绕
UtcNow
创建OO包装并不难。

我在程序中使用的方法是使用StopWatch类,如图所示

Stopwatch sw = new Stopwatch();
sw.Start();


// Critical lines of code

long elapsedMs = sw.Elapsed.TotalMilliseconds;

这不够专业:

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

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
更可靠的版本是:

PerformWork();

int repeat = 1000;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < repeat; i++)
{
   PerformWork();
}

sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds / repeat);
PerformWork();
int repeat=1000;
秒表sw=Stopwatch.StartNew();
for(int i=0;i

在我的实际代码中,我将添加GC.Collect调用以将托管堆更改为已知状态,并添加Sleep调用,以便在ETW配置文件中轻松分离不同的代码间隔。

因为我不太关心精度,所以我最后比较了它们。我在网络上捕获了很多数据包,我想确定收到每个数据包的时间。下面是测试500万次迭代的代码

    int iterations = 5000000;

    // Test using datetime.now
    {
        var date = DateTime.UtcNow.AddHours(DateTime.UtcNow.Second);

        var now = DateTime.UtcNow;

        for (int i = 0; i < iterations; i++)
        {
            if (date == DateTime.Now)
                Console.WriteLine("it is!");
        }
        Console.WriteLine($"Done executing {iterations} iterations using datetime.now. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
    }

    // Test using datetime.utcnow
    {
        var date = DateTime.UtcNow.AddHours(DateTime.UtcNow.Second);

        var now = DateTime.UtcNow;

        for (int i = 0; i < iterations; i++)
        {
            if (date == DateTime.UtcNow)
                Console.WriteLine("it is!");
        }
        Console.WriteLine($"Done executing {iterations} iterations using datetime.utcnow. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
    }

    // Test using stopwatch
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        var now = DateTime.UtcNow;

        for (int i = 0; i < iterations; i++)
        {
            if (sw.ElapsedTicks == DateTime.Now.Ticks)
                Console.WriteLine("it is!");
        }
        Console.WriteLine($"Done executing {iterations} iterations using stopwatch. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
    }
总之,如果您不太在意精度,那么DateTime.UtcNow是最快的。这也支持答案f
    int iterations = 5000000;

    // Test using datetime.now
    {
        var date = DateTime.UtcNow.AddHours(DateTime.UtcNow.Second);

        var now = DateTime.UtcNow;

        for (int i = 0; i < iterations; i++)
        {
            if (date == DateTime.Now)
                Console.WriteLine("it is!");
        }
        Console.WriteLine($"Done executing {iterations} iterations using datetime.now. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
    }

    // Test using datetime.utcnow
    {
        var date = DateTime.UtcNow.AddHours(DateTime.UtcNow.Second);

        var now = DateTime.UtcNow;

        for (int i = 0; i < iterations; i++)
        {
            if (date == DateTime.UtcNow)
                Console.WriteLine("it is!");
        }
        Console.WriteLine($"Done executing {iterations} iterations using datetime.utcnow. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
    }

    // Test using stopwatch
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        var now = DateTime.UtcNow;

        for (int i = 0; i < iterations; i++)
        {
            if (sw.ElapsedTicks == DateTime.Now.Ticks)
                Console.WriteLine("it is!");
        }
        Console.WriteLine($"Done executing {iterations} iterations using stopwatch. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
    }
Done executing 5000000 iterations using datetime.now. It took 0.8685502 seconds 
Done executing 5000000 iterations using datetime.utcnow. It took 0.1074324 seconds 
Done executing 5000000 iterations using stopwatch. It took 0.9625021 seconds