首页
社区
课程
招聘
重新认识线程sleep
发表于: 2024-11-8 09:24 1139

重新认识线程sleep

2024-11-8 09:24
1139

原本是自己实现一个类似超时的功能,代码如下:

1
2
3
for (int i = 0; i < 1500; i++) {
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
}

猜猜这段代码运行时间是多少?

按照之前的认知,这里就是1.5s的时间,即使有波动,也不会超过100ms。

但是,实际运行时间却超过了20多秒。

通过查资料,说是操作系统的调度问题,于是尝试提高当前线程的优先级,对于结果基本没有影响。

于是,打日志,分析每次时间执行的消耗是多少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
 
int main() {
    std::vector<std::chrono::steady_clock::time_point> timestamps;
 
    for (int i = 0; i < 1500; ++i) {
        timestamps.push_back(std::chrono::steady_clock::now());
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    timestamps.push_back(std::chrono::steady_clock::now());
 
    for (size_t i = 1; i < timestamps.size(); ++i) {
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(timestamps[i] - timestamps[i-1]);
        std::cout << "Sleep " << i << ": " << duration.count() << " ms\n";
    }
    return 0;
}

图片描述
结论是,每次的执行时间是15ms左右。纳尼,明明设置的休眠1ms,但是结果却休眠了15毫秒。怀疑人生了,在vs中,我用调试器逐行调试,发现每句执行的确实是1ms。

于是突然想到了一个关键词:颗粒度。查资料发现,系统有一个时间计时器分辨率的问题。于是msdn有答案了:
图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <windows.h>
#include <mmsystem.h> // 包含timeBeginPeriod和timeEndPeriod的定义
#pragma comment(lib, "winmm.lib") // 链接到winmm库
 
#include <iostream>
#include <chrono>
#include <thread>
 
int main() {
     
    TIMECAPS tc;
    if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) {
        std::cout << "The minimum supported resolution is: " << tc.wPeriodMin << " ms" << std::endl;
        std::cout << "The maximum supported resolution is: " << tc.wPeriodMax << " ms" << std::endl;
    }
    else {
        std::cout << "Failed to get timer device capabilities." << std::endl;
    }
 
    // 设置系统时钟分辨率为1ms
    MMRESULT result = timeBeginPeriod(1);
 
    // 运行延时代码
    std::cout << "Starting high-resolution timing test..." << std::endl;
    auto start = std::chrono::high_resolution_clock::now();
 
    for (int i = 0; i < 1500; i++) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
 
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double, std::milli> elapsed = end - start;
    std::cout << "Elapsed time: " << elapsed.count() << " ms" << std::endl;
 
    // 恢复系统时钟分辨率
    timeEndPeriod(1);
 
    return 0;
}

设置系统时钟分辨率为1之后,总的执行性时间为2s左右,基本合理了。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 562
活跃值: (4200)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
牛逼 我终于可以用sleep排序了
2024-11-8 10:13
0
游客
登录 | 注册 方可回帖
返回
//