假设有问题的机器上有未使用的执行资源可用,即并非所有 CPU 都在使用。如果一个线程正在等待一个条件变量,那么唤醒这个线程的相关成本是多少?同样,等待条件变量的相关成本是多少?我对粗略的量化和成本的来源都很感兴趣。就答案是“视情况而定”而言,我主要关心 x86/x64 上的最新版本的 Windows 和 Linux。
编辑:由于涉及内核调用,内核调用比常规函数调用贵多少?
假设有问题的机器上有未使用的执行资源可用,即并非所有 CPU 都在使用。如果一个线程正在等待一个条件变量,那么唤醒这个线程的相关成本是多少?同样,等待条件变量的相关成本是多少?我对粗略的量化和成本的来源都很感兴趣。就答案是“视情况而定”而言,我主要关心 x86/x64 上的最新版本的 Windows 和 Linux。
编辑:由于涉及内核调用,内核调用比常规函数调用贵多少?
我不知道有关 pthread 或 D 实现的任何细节,但总的来说,条件变量的最佳情况开销是一个额外的内核调用和可能的上下文切换。
典型的实现只是事件和互斥体的包装器,因此开销和时间可以通过这些内核对象的行为来表征。在等待线程放弃其预定时间量的剩余部分,并在唤醒线程由内核调度并根据其优先级获得下一个可用时间量。这在很大程度上取决于负载和内核配置,但通常会在几毫秒内。
对于条件变量,还有重新获取互斥锁的额外任务,这当然可能会阻塞。如果它没有阻塞,那么它仍然是内核调用。这可能最终被优化为一些原子 CPU 指令,相比之下这些指令非常快,但仅限于单个进程。[编辑:例如,Win32 中的 CRITICAL_SECTION 或 Linux 中的 futex。]
最坏的情况是条件变量被虚假触发,线程醒来后发现无事可做,但这通常占总开销的一小部分。
要回答你的最后一个问题:
由于涉及内核调用,内核调用比常规函数调用贵多少?
是的,大约贵 1000 倍。
这与您的问题有关,尽管我认为这不是您正在寻找的答案。
我们对信号与互斥体/条件进行了基准测试,以查看哪种方法可以更快地休眠和唤醒线程。对于信号,我们使用 sigwait() 暂停并使用 pthread_kill 唤醒。对于互斥体/条件我们为每个线程使用了一个互斥体和一个条件。我们发现使用信号可以将线程睡眠和唤醒速度提高 5 倍。
我们没有测试 futex。