秒表似乎跳了500µ;s在紧循环的迭代之间

本文关键字:循环 之间 迭代 #181 | 更新日期: 2023-09-27 18:28:55

我写了一些代码,使用紧密循环来监控Stopwatch的输出。此循环跟踪自上次迭代以来经过的刻度数。我观察到每秒20次500微秒的跳跃,而大多数其他迭代需要<1µs。

有人能解释一下我为什么看到这些跳跃吗?

我试过:

  1. 设置处理器相关性(无效)
  2. 更改线程优先级(最高/高于正常会使情况变得更糟)
  3. 在调试器之外运行
  4. 发布带有优化的内部版本

我的代码如下:

        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;
            }
        }

秒表似乎跳了500µ;s在紧循环的迭代之间

您很可能看到抢占式任务切换。这是指操作系统挂起您的程序,然后关闭以执行其他程序。这就是自Windows 95以来的情况(Win 3.1和更早版本具有协作多任务处理功能,您可以随心所欲地使用CPU)。

顺便说一句,有一种更好的方法可以准确地为执行计时:QueryThreadCycleTime,它只在代码执行时计算CPU周期,因此排除了这种暂停。

您的测试实际上没有意义。。。您的进程并不是唯一一个在您的机器上运行的进程。系统依次为每个线程提供处理器时间,因此有一段时间你的循环根本没有运行,这就解释了"跳跃"。