我一直在为多媒体消息构建一个高吞吐量的服务器应用程序,实现语言是C++。每台服务器可以独立使用,也可以将多台服务器连接在一起,创建一个基于 DHT 的覆盖网络;服务器就像 Skype 的情况一样,就像超级对等点一样。
工作正在进行中。目前,服务器每秒可以处理大约 200,000 条消息(256 字节消息),并且在我的机器(Intel i3 Mobile 2 GHz、Fedora Core 18(64 位)、4 GB RAM)上的最大吞吐量约为 256 MB/s长度为 4096 字节的消息。服务器有两个线程,一个用于处理所有 IO(基于 epoll,边缘触发),另一个用于处理传入消息。覆盖管理还有另一个线程,但在当前讨论中并不重要。
讨论中的两个线程使用两个循环缓冲区共享数据。线程 1 使用一个循环缓冲区为线程 2 排队新消息,而线程 2 通过另一个循环缓冲区返回处理后的消息。服务器完全无锁。我没有使用任何同步原语,甚至没有使用原子操作。
循环缓冲区永远不会溢出,因为消息是池化的(在开始时预先分配)。事实上,所有重要/经常使用的数据结构都被池化以减少内存碎片并提高缓存效率,因此我们知道在服务器启动时我们将要创建的最大消息数,因此我们可以预先计算最大值缓冲区的大小,然后相应地初始化循环缓冲区。
现在我的问题:线程 #1 一次将序列化消息排入队列(实际上是指向消息对象的指针),而线程 #2 以块的形式从队列中取出消息(32/64/128 的块),然后返回通过第二个循环缓冲区以块的形式处理消息。如果没有新消息,线程 #2 会一直忙于等待,从而使 CPU 内核之一一直处于忙碌状态。如何进一步改进设计?忙碌等待策略的替代方案是什么?我想优雅而高效地做到这一点。我考虑过使用信号量,但我担心这不是最好的解决方案,原因很简单,每次我在线程 #1 中排队一条消息时都必须调用“sem_post”,这可能会大大降低吞吐量,第二个线程必须调用“sem_post”等于防止信号量溢出的次数。另外我担心信号量实现可能在内部使用互斥锁。
第二个不错的选择可能是使用信号,如果我可以发现仅当第二个线程“清空队列并且正在调用 sigwait”或“已经在 sigwait 上等待”时才发出信号的算法,简而言之就是信号必须至少提高几次,尽管如果信号的提高次数比需要的多几次也不会受到伤害。是的,我确实使用了 Google 搜索,但我在 Internet 上找到的解决方案都不令人满意。以下是一些注意事项:
A. 服务器在进行系统调用时必须浪费最少的 CPU 周期,并且必须使用最少的系统调用次数。
B. 必须有非常低的开销并且算法必须是高效的。
C. 没有任何锁定。
我希望所有选项都摆在桌面上。
这是我共享服务器信息的网站的链接,以便更好地了解其功能和目的:www.wanhive.com