我正在使用qt5和c ++在Windows 10中为一些复杂的通信应用程序编写一个计时器。我希望使用最高3%的CPU和微秒级分辨率。
最初我在这个应用程序中使用qTimer(qt5)。 CPU使用率低,开发人员友好的界面很好。但它并不精确,因为我需要。它只需要毫秒作为参数,但我需要微秒。并且在许多真实情况下,例如cpu上的重负载,计时器的准确度不等于此分辨率。有时计时器会以1毫秒的速度点火,有时会达到15毫秒。你可以在图片中看到这个问题:
我搜索了几天的解决方案。但最后我发现Windows是一个非实时操作系统(RTOS),并没有提供高分辨率和精确的计时器。
我编写了自己的高分辨率精确计时器,并通过CPU轮询实现此目标。我开发了一个单独的线程工作的单例类。它以10微秒的分辨率工作。
但它消耗了CPU中的一个逻辑核心。相当于ryzen 2700的6.25%。
对于我的应用程序,这种CPU使用率是不可接受的。如何在不提供高分辨率的情况下减少CPU使用率?
这是完成工作的代码:
void CsPreciseTimerThread::run()
{
while (true)
{
QMutexLocker locker(&mMutex);
for (int i=0;i<mTimerList.size();i++)
{
CsPreciseTimerMiddleLayer* timer = mTimerList[i];
int interval = timer->getInterval();
if ( (timer->isActive() == true&&timer->remainingTime()<0))
{
timer->emitTimeout();
timer->resetTime();
}
}
}
}
我试图降低计时器线程的优先级。我用这句话:
QThread::start(QThread::Priority::LowestPriority);
还有这个:
QThread::start(QThread::Priority::IdlePriority);
这种变化使计时器不太精确,但CPU使用率没有降低。
之后,我尝试强制当前线程在循环中休眠几微秒。
QThread::usleep(15);
正如你可能猜到的那样睡眠功能确实搞砸了准确性。有时计时器睡眠时间超过预期,如10毫秒或15毫秒。
我将直接引用Windows API而不是Qt抽象。
我认为您不想降低线程优先级,我认为您希望提高线程优先级并在轮询之间使用最小量的Sleep来平衡延迟和CPU开销。
两个想法:
THREAD_PRIORITY_TIME_CRITICAL
。然后在完成Sleep循环后做一个非常小的for
。此睡眠量应介于0..10毫秒之间。需要进行一些实验,但我会在下一次预期的超时时间内停留不超过一半的时间,最长为10毫秒。当你在计时器的N微秒内时,你可能需要旋转而不是屈服。需要进行一些实验。你也可以尝试将你的Process priority提升到REALTIME_PRIORITY_CLASS
。注意 - 少数失控的进程和处于这些较高优先级的线程未休眠可能会锁定系统。