我有一个包装一些IO库的异步API。该库使用C样式回调,API是C ++,因此自然选择(IMHO)是使用int
来构建此API。像std::future/std::promise
这样的东西。但是,当我测试实现时,我发现瓶颈是std::future<void> Read(uint64_t addr, byte* buff, uint64_t buffSize)
,更确切地说,future/promise
用于实现futex
。由于futex,AFAIK是用户空间和我知道同步两个线程的最快机制,我只是转而使用原始futexes,这在某种程度上改善了情况,但不是那么激烈。性能漂浮在每秒约200k futex WAKE的每秒。然后我偶然发现了这篇文章 - Futex Scaling for Multi-core Systems,它与我用futexes观察到的效果相当。我的问题是,因为futex对我来说太慢了,Linux上我用来唤醒等待的最快机制是什么。我不需要比二进制信号量更复杂的东西,只是为了表示IO操作完成。由于IO操作非常快(几十微秒),因此无法选择切换到内核模式。繁忙的等待也不是一个选择,因为在我的情况下CPU时间是宝贵的。
底线,用户空间,简单同步原语,仅在两个线程之间共享,只有一个线程设置完成,只有一个线程等待完成。
EDIT001: 如果...之前我曾说过,在忙碌的等待中没有旋转。但是futex已经在忙碌的等待中旋转了吧?但是实现涵盖了更一般的情况,它请求全局哈希表,保存虚拟引擎,所有订阅者的队列等。在一些简单的实体(如int)上模仿相同的行为是一个好主意,没有锁,没有原子,没有全球数据结构和繁忙的等待就像futex已经做到的那样?