【发布时间】:2017-05-09 17:49:53
【问题描述】:
我正在编写一个读写器队列,它需要尽可能低的延迟。 writer 的频率不足以让 reader 一直忙,所以在常见的实现中,如果 queue 为空,reader 会等待锁并进入睡眠状态。当某些东西被放入队列时,阅读器被唤醒,然而,这会导致上下文切换并引入延迟。另一种方法是使用自旋锁,但它使用原子操作,本质上锁定在总线上,因此会导致总线上的大量负载,影响其他作业的性能。
我的问题是,有没有办法让阅读器处于空闲状态,而不产生 CPU,但同时不会导致总线负载过重,并且每当有东西进入时,它可以退出空闲状态并立即继续.目标是使从放入队列的内容到阅读器开始处理它的延迟尽可能低。我可以为 reader 线程分配一个专用的 CPU core,所以 reader 空闲时 CPU 被浪费不是问题。
有什么想法吗?
【问题讨论】:
-
你可以旋转,也可以阻挡,中间没有任何东西。
sys_futex将是最轻量级的东西,如果你想阻止(但也是最不便携的)。大多数时候,一个人不想在大多数时候旋转或阻塞(但使用原子操作来对队列进行无锁修改)并且阻塞,从不旋转,当一些“特殊”情况发生时,例如队列满或队列空. -
@Damon,它不必是可移植的。看起来 sys_futex 仍然有一个等待队列并在等待时产生 CPU,不是吗?基本上我想要的是,在等待时,线程不会放弃 CPU,而是运行一些循环运行空闲指令,这些指令不会将负载放到总线上。每当有东西放入队列时,写入器都会以某种方式向读取器线程发出信号,使其退出循环。
-
您必须在多核系统上运行,并且必须找到一种方法将您的阅读器进程固定到内核,并为该进程禁用上下文切换,这样它就可以休眠而不会引起上下文切换.如果没有内核级别的黑客攻击,您可能无法做到这一点。
-
@icando:在循环中运行空闲指令正在旋转,这不好。在无事可做(没有什么有用)可做时放弃 CPU 是正确的。
sys_futex确实做到了,而且开销尽可能低。你可以做的是实现一个协程系统(使用宏hacks或setjmp/longjmp,也有现成的C库可以做到这一点)。所有的协程实现或多或少都是丑陋的 hack,但如果你不想放弃 CPU,运行协程的好处是你可以同时做有用的东西而不是旋转。跨度> -
@Damon,正如我所说,我要优化的是延迟,所以浪费CPU而不做任何事情是可以的。即使使用 sys_futex,当您将线程置于睡眠状态并唤醒它时,上下文切换和进出内核空间仍然存在开销,这是我想要避免的开销。至于协程,当协程运行时,读者不能立即运行,而是等待协程放弃CPU,这是完全不能接受的。
标签: linux multithreading linux-kernel