秒表似乎跳了500µ;s在紧循环的迭代之间
本文关键字:循环 之间 迭代 #181 | 更新日期: 2023-09-27 18:28:55
我写了一些代码,使用紧密循环来监控Stopwatch的输出。此循环跟踪自上次迭代以来经过的刻度数。我观察到每秒20次500微秒的跳跃,而大多数其他迭代需要<1µs。
有人能解释一下我为什么看到这些跳跃吗?
我试过:
- 设置处理器相关性(无效)
- 更改线程优先级(最高/高于正常会使情况变得更糟)
- 在调试器之外运行
- 发布带有优化的内部版本
我的代码如下:
Stopwatch sw = new Stopwatch();
int crossThresholdCount = 0;
long lastElapsedTicks = 0;
long lastPrintTicks = 0;
Console.WriteLine("IsHighResolution: " + Stopwatch.IsHighResolution);
Console.WriteLine("Frequency: " + Stopwatch.Frequency);
sw.Start();
long thresholdTicks = 5000; // 10000 ticks per ms
while (true)
{
long tempElapsed = sw.ElapsedTicks;
long sincePrev = tempElapsed - lastElapsedTicks;
lastElapsedTicks = tempElapsed;
if (sincePrev > thresholdTicks)
crossThresholdCount++;
// print output
if (crossThresholdCount > 0 && tempElapsed - lastPrintTicks > TimeSpan.TicksPerSecond)
{
lastPrintTicks = tempElapsed;
Console.WriteLine("crossed " + crossThresholdCount + " times");
crossThresholdCount = 0;
}
}
您很可能看到抢占式任务切换。这是指操作系统挂起您的程序,然后关闭以执行其他程序。这就是自Windows 95以来的情况(Win 3.1和更早版本具有协作多任务处理功能,您可以随心所欲地使用CPU)。
顺便说一句,有一种更好的方法可以准确地为执行计时:QueryThreadCycleTime
,它只在代码执行时计算CPU周期,因此排除了这种暂停。
您的测试实际上没有意义。。。您的进程并不是唯一一个在您的机器上运行的进程。系统依次为每个线程提供处理器时间,因此有一段时间你的循环根本没有运行,这就解释了"跳跃"。