由于我希望在对象创建池中使用一些计时统计信息来动态优化其性能,因此我需要知道添加Stopwatch 来监控计时是否会对对象创建的性能产生不利影响。我想为典型的对象创建计时(大约 20-30 毫秒)以优化创建它们的任务的超时时间,但前提是添加 Stopwatch 不会显着减慢循环。
所以我编写了这个测试程序来分别计算Start()、Stop() 的创建开销和Stopwatch 的经过时间检索。
using System;
using System.Diagnostics;
namespace SO9925598_Stopwatch_overhead
{
class Program
{
private const int nLoops = 10000;
private const double nLoopsDouble = nLoops;
private const int waitTime = 2; //ms
static void Main(string[] args)
{
Stopwatch stopwatchTimingTheTest = new Stopwatch();
double frequencyConversionFactor = 1000.0 / Convert.ToDouble(Stopwatch.Frequency); // ms per click
Stopwatch stopwatchUnderTest;
// Instantiation
for (int i = 0; i < nLoops; i++)
{
stopwatchTimingTheTest.Start();
stopwatchUnderTest = new Stopwatch();
stopwatchTimingTheTest.Stop();
stopwatchUnderTest = null;
}
long elapsed = stopwatchTimingTheTest.ElapsedTicks;
double overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Creation overhead {overhead} ms per Stopwatch instantiation. (Based on {nLoops} trials).");
// Further tests can all use the same object
stopwatchUnderTest = new Stopwatch();
// Start
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchTimingTheTest.Start();
stopwatchUnderTest.Start();
stopwatchTimingTheTest.Stop();
stopwatchUnderTest.Stop();
elapsed = stopwatchUnderTest.ElapsedTicks;
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.Start() overhead {overhead} ms.");
// Stop
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchTimingTheTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Stop();
elapsed = stopwatchUnderTest.ElapsedTicks;
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.Stop() overhead {overhead} ms.");
// Elapsed ticks
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Start();
elapsed = stopwatchUnderTest.ElapsedTicks;
stopwatchTimingTheTest.Stop();
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.ElapsedTicks overhead {overhead} ms.");
// Elapsed ticks
stopwatchTimingTheTest.Reset();
for (int i = 0; i < nLoops; i++)
{
stopwatchUnderTest.Start();
stopwatchUnderTest.Stop();
stopwatchTimingTheTest.Start();
elapsed = stopwatchUnderTest.ElapsedMilliseconds;
stopwatchTimingTheTest.Stop();
}
elapsed = stopwatchTimingTheTest.ElapsedTicks;
overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
Console.WriteLine($"Stopwatch.ElapsedMilliseconds overhead {overhead} ms.");
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
结果如下:
Creation overhead 0,00011756 ms per Stopwatch instantiation. (Based on 10000 trials).
Stopwatch.Start() overhead 0,000256 ms.
Stopwatch.Stop() overhead 0,00023665 ms.
Stopwatch.ElapsedTicks overhead 0,00010946 ms.
Stopwatch.ElapsedMilliseconds overhead 0,00011758 ms.
时间是基于 10000 个样本的方法每次调用的平均时间。
该程序运行在一台装有 Intel Core i7-8850H CPU、频率为 2.60 GHz 的计算机上,运行 Windows 10 操作系统。
结论:对于我的应用程序,对象创建时间为 20-30 毫秒,Stopwatch 的开销可以忽略不计。