Windows下std::this_thread:sleep_for()休眠精度问题

在开发NES模拟器时遇到Windows下std::this_thread::sleep_for()精度问题,导致帧率低于预期。Mac OS上精度可达微秒级别,而Windows默认最低为15毫秒。通过timeBeginPeriod(1)可提高精度至1-2毫秒,但可能影响系统性能。SFML游戏引擎在Windows和Mac上都能稳定限制帧率为60,其限制帧率方式不明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Windows下std::this_thread:sleep_for()休眠精度问题

最近在开发一个NES模拟器,想自己实现一个简单的像素游戏引擎用来渲染NES输出的图像。NES系统能输出60帧的图像,所以我希望游戏引擎能将帧率限制在60帧。最简单的方法就是用sleep控制每次主循环的时间。但同样的代码,在Mac OS和Windows上出现了不同的结果。

在Mac OS上,程序运行符合预期,可以稳定输出60帧,但在Windows上,程序运行变得非常慢,大概30多帧左右。经过几天的研究,发现是Windows下sleep的精度不够。

先说结论,Windows下的sleep,在我的Windows(Windows 11)电脑上,默认最低只能休眠15毫秒左右,而在我的Mac上,精度可以达到微秒级别。测试代码

下面是Mac OS下,sleep的测试结果:

-> sleep 1ms tests
std::this_thread::sleep_for() 1257us
unix usleep() 1255us
unix nanosleep
### std::this_thread::sleep_forSleep 函数的区别 #### 1. 跨平台性 `std::this_thread::sleep_for` 是 C++11 标准库中提供的跨平台函数,能够在不同操作系统上实现一致的行为[^1]。相比之下,`Sleep` 是 Windows 平台特有的 API 函数,仅在 Windows 系统上可用。如果需要编写跨平台代码,推荐使用 `std::this_thread::sleep_for`。 #### 2. 参数类型 `std::this_thread::sleep_for` 使用的是 `std::chrono::duration` 类型作为参数,支持多种时间单位(如秒、毫秒、微秒等),并且可以更灵活地定义休眠时间[^2]。例如: ```cpp std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 休眠 1000 毫秒 ``` 而 `Sleep` 的参数是简单的整数类型,表示以毫秒为单位的休眠时间。例如: ```cpp Sleep(1000); // 休眠 1000 毫秒 ``` #### 3. 系统时间依赖性 `std::this_thread::sleep_for` 存在一个设计缺陷:在某些平台上(如 Windows),如果系统时间被修改,可能会导致线程一直处于睡眠状态[^1]。这种问题在 Linux 平台上通常不会出现。因此,在需要高可靠性的场景下,可能需要额外处理系统时间变化的情况。 `Sleep` 函数则不依赖系统时间的变化,无论系统时间如何调整,它都能按照指定的时间间隔唤醒线程。 #### 4. 头文件和命名空间 `std::this_thread::sleep_for` 需要包含 `<thread>` 和 `<chrono>` 头文件,并且需要使用 `std::this_thread` 命名空间。例如: ```cpp #include <thread> #include <chrono> std::this_thread::sleep_for(std::chrono::seconds(1)); ``` `Sleep` 函数需要包含 `<windows.h>` 头文件,并且不需要任何命名空间。例如: ```cpp #include <windows.h> Sleep(1000); ``` #### 5. 返回值 `std::this_thread::sleep_for` 是一个无返回值的函数,调用后直接阻塞当前线程直到指定时间结束[^2]。而 `Sleep` 同样没有返回值,行为与 `std::this_thread::sleep_for` 类似。 #### 6. 替代方案 在跨平台开发中,如果需要避免 `std::this_thread::sleep_for` 的系统时间依赖性问题,可以考虑使用 `std::this_thread::yield` 或者其他第三方库(如 Boost)提供的定时器功能[^4]。此外,在特定平台上也可以选择本地 API 函数,例如在 Windows 上使用 `Sleep`,在 Linux 上使用 `usleep` 或 `nanosleep`。 ### 示例代码对比 #### 使用 `std::this_thread::sleep_for` ```cpp #include <iostream> #include <thread> #include <chrono> int main() { std::cout << "Start\n"; std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "End\n"; return 0; } ``` #### 使用 `Sleep` ```cpp #include <iostream> #include <windows.h> int main() { std::cout << "Start\n"; Sleep(1000); std::cout << "End\n"; return 0; } ``` ### 总结 - `std::this_thread::sleep_for` 更适合跨平台开发,但可能存在系统时间依赖性的问题。 - `Sleep` 是 Windows 平台专用函数,简单易用,但不具备跨平台能力。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值