C ++主循环偶尔会出现断断续续的情况

我遇到了一个问题,我的游戏循环结构每秒接近一次(可变间隔)。 一个单帧然后超过60毫秒,而所有其他的需要less于1毫秒。

简化了很多之后,我用下面的程序来重现错误。 它只测量帧时间并报告。

#include <iostream> #include "windows.h" int main() { unsigned long long frequency, tic, toc; QueryPerformanceFrequency((LARGE_INTEGER*)&frequency); QueryPerformanceCounter((LARGE_INTEGER*)&tic); double deltaTime = 0.0; while( true ) { //if(deltaTime > 0.01) std::cerr << deltaTime << std::endl; QueryPerformanceCounter((LARGE_INTEGER*)&toc); deltaTime = (toc - tic) / double(frequency); tic = toc; if(deltaTime < 0.01) deltaTime = 0.01; } } 

再多一个帧比其他帧慢得多。 添加if让错误消失(cerr从未被调用)。 我原来的问题不包含任何cerr / cout。 但是,我认为这是对同样错误的再现。

cerr在每次迭代中都被刷新,所以这不是创build单个慢帧所发生的情况。 我从剖析器(Very Sleepy)知道stream内部使用了一个锁/关键部分,但是这不应该改变任何东西,因为程序是单线程的。

是什么导致单个迭代失去了那么多?

编辑 :我做了更多的testing:

  • 添加std::this_thread::sleep_for( std::chrono::milliseconds(7) ); 因此减less进程的CPU使用率不会改变任何东西。
  • printf("%f\n", deltaTime); 问题就消失了(也许是因为它不使用与stream相反的互斥锁和内存分配)

windows的设计并不能保证任何执行时间的上限,因为它使用某种逻辑动态地为所有程序分配运行时资源 – 例如,调度器将把资源分配给高优先级的进程,从而使较低优先级的进程有些情况。 如果程序运行紧密的循环并消耗大量CPU资源,程序在统计上更可能最终受到这种事情的影响。 因为 – 最终 – 调度程序将暂时提高正在挨饿的程序的优先级和/或减少挨饿的程序的优先级(在你的情况下,通过运行一个紧密的循环)。

使输出为std::cerr有条件不会改变这种情况的事实 – 它只是改变了在指定的时间间隔内发生的可能性,因为它改变了程序在循环中使用系统资源的方式,因此改变了它如何与系统调度程序,策略等进行交互

这种事情影响所有非实时操作系统中运行的程序,但是具体影响取决于每个操作系统的实现方式(例如调度策略,其他策略控制程序访问资源等)。 总是有一个非零的概率(即使它很小)发生这样的摊位。

如果你想在这样的事情上没有停顿的绝对保证,你将需要一个实时操作系统。 这些系统被设计用来在一个定时的意义上做更可预测的事情,但是这也是需要权衡的,因为它也要求你的程序的设计必须知道它们必须在指定的时间间隔内完成特定功能的执行。 实时操作系统使用不同的策略,但是如果程序没有考虑到这种情况,那么执行约束的时间可能会导致程序发生故障。

我不确定,但可能是因为系统中断你的主线程让其他人运行,而且由于它需要一些时间(我记得在我的Windows XP电脑上,量程是10毫秒),它会停止一帧。

这是非常明显的,因为它是一个单线程的应用程序,如果你使用多个线程,它们通常在处理器的几个内核上分派(如果可用的话),并且这些分区仍然在这里,但是不太重要(如果你实现了你的应用程序逻辑对)。

编辑: 在这里你可以有更多关于Windows和Linux调度器的信息。 基本上,Windows使用量子(在Windows server上从几毫秒到120毫秒不等)。

编辑2:你可以在这里看到有关Windows调度器的更详细的解释 。