只是在测试这两个小程序,

#include <thread>

int main()
{
    for (int i = 0; i < 10000000; i++)
    {
        std::this_thread::yield();
    }

    return 0;
}

以及:

#include <thread>
#include <chrono>

int main()
{
    using namespace std::literals;

    for (int i = 0; i < 10000000; i++)
    {
        std::this_thread::sleep_for(0s);
    }

    return 0;
}

我在我的系统上获得了各自的时间(Ubuntu 22.04LTS,内核版本5.19.0-43-Generic),

./a.out  0,33s user 1,36s system 99% cpu 1,687 total

以及:

./a.out  0,14s user 0,00s system 99% cpu 0,148 total

为什么std::this_thread::yield()std::this_thread::sleep_for(0s)慢10倍?

注:g++和clang++之间的时序相似.

编辑:正如答案中指出的,这是对STL实现的优化,调用sleep(0)实际上要慢300倍(50us对150 ns).

推荐答案

快速浏览一下this_thread::sleep_forsource

template<typename _Rep, typename _Period>
inline void
sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
{
    if (__rtime <= __rtime.zero())
      return;
    ...

因此sleep_for(0s)什么都不做,实际上您的测试程序使用0.0s的系统时间,基本上是一个完全在用户空间运行的空循环(事实上,我怀疑如果您使用优化进行编译,则使用it will be completely removed)

On the other hand, yield calls* sched_yield which in turns will call schedule() in kernel space, thus at least executing some logic to check if there is another thread to schedule.

我相信你的0.33s的用户空间时间基本上是系统调用开销.

*实际上跳到__libcpp_thread_yield,然后调用sched_yield,至少在Linux上

Linux相关问答推荐

Linux 中大型 TSV 的条件编辑

Perl/cpan: 找不到 JSON/Parse.pm @INC

为什么 liburing 写入性能低于预期?

为什么我在从 Linux 通过 telnet 发送 Ctrl-C 后停止接收数据?

如何更改文件的上次访问/修改/更改日期?

如何为命令的所有选项启用无密码 sudo?

当未在日志(log)中输入确切的时间戳时如何过滤日期范围内的值

当接收端未从套接字读取时,通过 Unix 套接字发送的消息会发生什么情况?

Stripping linux 共享库

为什么 perf 不报告缓存未命中?

Git为每次推送输入长密码

linux远程执行命令

如何计算列的平均值

什么是适用于 Linux 的好的 Prolog IDE?

如何等待第一个命令完成?

如何自动化 HTML 到 PDF 的转换?

/dev/random 非常慢?

从文件中随机 Select 行而不用 Unix 啜饮它

如何限制我网站的 API 用户?

如何查看线程在哪个 CPU 内核中运行?