测量C#函数的时间周期的最佳方法是什么?

时间:2011-01-11 02:37:14

标签: c#

真的,我正在寻找一个很好的功能,可以在Windows操作系统下准确测量给定C#功能的时间周期。我尝试了这些功能,但它们都没有得到准确的测量:

DateTime StartTime = DateTime.Now;      
TimeSpan ts = DateTime.Now.Subtract(StartTime);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
//code to be measured
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed; 

真的,每次我打电话给他们,他们给我不同的时间来做同样的功能

如果有人知道准确测量时间的更好方法,请帮助我,并且非常感谢

7 个答案:

答案 0 :(得分:7)

秒表是测量功能执行所需时间的推荐方法。由于各种软件和硬件因素,从运行到运行永远不会是相同的,这就是性能分析通常在大量运行中完成并且时间平均的原因。

答案 1 :(得分:4)

"他们给了我相同功能的不同时间" - 那是预料之中的。事情起伏不定,因为你不是系统上运行的唯一进程。

运行您想要在大循环中计时的代码以平均任何波动(将总时间除以循环次数)。

Stopwatch是一个准确的计时器,对于大多数情况来说都是足够的时间。

const int numLoops = 1000000;   // ...or whatever number is appropriate

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

for (int i = 0; i < numLoops; i++)
{
    // code to be timed...
}

stopWatch.Stop();
TimeSpan elapsedTotal = stopWatch.Elapsed;
double timeMs = elapsedTotal.TotalMilliseconds / numLoops;

答案 2 :(得分:1)

黄金标准是使用StopWatch。它是一个高分辨率计时器,效果非常好。

我建议您使用.Elapsed.TotalMilliSeconds检查已用时间,因为您获得的是double,而不是.Elapsed.MilliSeconds,这会为您提供int。这可能会导致你的结果失败。

此外,您可能会发现在计时测试期间会发生垃圾收集,这些可能会显着改变生成的时间。在计时测试之前和之后检查GC收集计数是有用的,如果发生任何垃圾收集,则丢弃结果。

否则,您的结果可能会因为其他线程和进程在测试期间接管CPU和其他系统资源而有所不同。除了多次运行测试并通过计算平均值和计算结果进行统计分析之外,您无法在此处执行任何操作。标准偏差时间等。

我希望这会有所帮助。

答案 3 :(得分:1)

虽然您可以在时钟周期内测量代码,但它仍然会像在几秒钟内测量一样容易变化,并且将不那么有用(因为秒是一样好,如果不是更好,一个单位测量比时钟周期)。获得不受其他进程影响的测量的唯一方法是确保没有运行,并且您无法在Windows上执行此操作 - 操作系统本身将始终运行某些操作,因为它不是单进程操作系统

您最接近测量的是建立并运行代码as described here。然后,您可以通过在代码开头设置断点,然后逐步执行查看x86程序集以获取要计时的方法的JIT代码。您可以在英特尔架构手册中交叉引用每条x86指令及其周期时序,并将它们相加以获得准确的周期计数。

这当然是非常痛苦的,基本上没用。它也可能因代码更改而失效,导致JIT采用稍微不同的方法从IL生成x86。

答案 4 :(得分:1)

您需要探查器来衡量代码执行(请参阅What Are Some Good .NET Profilers?开始搜索)。

查看您的评论,目前还不清楚您要优化的内容。通常,当代码执行1000次并且纯粹是CPU绑定时,您需要调低CPU时钟周期,在其他情况下,每个函数的执行时间通常就足够了。但是你说你的代码太慢而无法多次运行来计算秒表的平均时间。

您还需要弄清楚CPU是否是您的应用程序的瓶颈,或者还有其他一些因素导致它变慢。查看TaskManager中的CPU%可以为您提供有关它的信息 - 少于100%的CPU使用率几乎可以保证其他东西(即网络或磁盘活动)使程序变慢。

基本上提供有关您尝试衡量的代码类型的更多详细信息,以便更轻松地帮助您。

答案 5 :(得分:0)

回应其他人:秒表课是最好的方法。

回答有关仅测量时钟周期的问题:您在现代处理器上运行多任务操作系统的事实使得测量时钟周期几乎无用。上下文切换很有可能从处理器缓存中删除您的代码和数据,操作系统可能决定在此期间交换您的工作集。

处理器可以决定根据缓存等待或内存访问重新排序指令,并在等待时执行它可以执行的操作。或者它可能不在缓存中。

因此,简而言之,执行多次运行并对它们求平均值是唯一可行的方法。

为了减少时间内的抖动,你可以提升线程/进程的优先级,但这可能会导致一系列其他问题(突然变为实时优先级,并且陷入长循环会基本停止所有其他处理。如果发生错误,并且您陷入无限循环,您唯一的选择是重置按钮),并且根本不推荐,特别是在用户计算机或生产环境中。并且由于您无法在重要的地方执行此操作,因此您在计算机中运行的基准测试将进行任何优先级修改,无效。

答案 6 :(得分:0)

如何使用Environment.TickCount来捕获开始和结束,然后使用TimeSpan.FromTicks()来捕获它?