使用std::chrono实现稳定更新循环的帧抖动问题咨询
关于std::chrono实现固定间隔循环的抖动问题解答
代码逻辑评估
你的实现逻辑不存在bug,是固定间隔循环的标准正确写法:
- 选用
std::chrono::steady_clock单调时钟,避免系统时间调整导致的间隔错误 - 采用「目标时间累加」+
sleep_until的逻辑,而非每次调用sleep_for(100ms),避免了工作逻辑耗时带来的误差累计问题
bool firstUpdate = true; std::chrono::time_point<std::chrono::steady_clock> lastUpdateTime; std::chrono::time_point<std::chrono::steady_clock> lastUpdateProf; while (true) { if (firstUpdate) { lastUpdateTime = std::chrono::steady_clock::now(); firstUpdate = false; } lastUpdateTime = lastUpdateTime + std::chrono::milliseconds(100); // Do the work, generate data and send data .... // Sleep if necessary std::this_thread::sleep_until(lastUpdateTime); // Additional profiling of frame duration auto now = std::chrono::steady_clock::now(); std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(now - lastUpdateProf).count() << std::endl; lastUpdateProf = now; }
抖动表现合理性说明
你测得的±2ms抖动完全属于Windows 10非实时桌面平台的正常预期,主要有以下几个原因:
- Windows为通用桌面操作系统,不提供硬实时调度保证,你的用户态线程随时可能被更高优先级的系统线程、硬件中断处理程序、其他后台进程抢占CPU,导致唤醒延迟
- 默认情况下Windows系统的定时器时钟粒度为10~15.6ms,即便
sleep_until指定了精确的唤醒时间,操作系统也只会在时钟中断触发时检查线程唤醒条件,天然存在毫秒级的调度误差 - 标准库的
std::this_thread::sleep_until底层依赖系统定时器实现,本身就只提供最佳努力的唤醒保证,不承诺绝对精度
可选优化方案
如果需要进一步降低抖动,可以采取以下Windows平台专属优化手段:
- 调用Win32 API
timeBeginPeriod(1)将系统定时器精度临时提升到1ms,使用完成后调用timeEndPeriod(1)恢复系统默认设置,可将抖动压缩到±1ms左右 - 适当提升工作线程的调度优先级,例如调用
SetThreadPriority将线程优先级设置为THREAD_PRIORITY_HIGHEST,减少被其他线程抢占的概率 - 优化工作逻辑,避免在循环内调用可能产生阻塞的IO、锁等待操作,减少不可控的耗时波动
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

