2013-02-25 181 views
11

我正在实现需要维护非常大数量(100K或更多)长连接的自定义服务器。服务器只是在套接字之间传递消息,并没有做任何严肃的数据处理。消息很小,但其中许多消息每秒都会收到/发送。减少延迟是目标之一。我意识到使用多核并不会提高性能,因此我决定通过调用run_onepoll方法io_service对象在单线程中运行服务器。无论如何,多线程服务器将更难实施。Boost Asio单线程性能

什么是可能的瓶颈?系统调用,带宽,完成队列/事件解复用?我怀疑调度处理程序可能需要锁定(这是由asio库内部完成的)。是否可以禁用boost.asio中的队列锁定(或任何其他锁定)?

编辑:相关的问题。多线程可以提高系统调用性能吗?我的感觉是,因为系统调用是内核原子/同步的,添加更多的线程不会提高速度。

+0

如果您在一个线程中运行所有内容,则不需要任何(手写)锁。 – 2013-02-25 18:29:23

+1

使用多核可能会提高性能 - 请参阅http://cmeerw.org/blog/748.html#748和http://cmeerw.org/blog/746.html#746,了解去年所做的一些基准测试。 – cmeerw 2013-02-25 19:58:30

回答

15

您可能想要阅读几年前的my question,当我在开发系统软件Blue Gene/Q supercomputer时首次调查Boost.Asio的可伸缩性时询问了它。

扩展到100k或更多的连接应该不成问题,但您需要了解明显的资源限制,例如打开的文件描述符的最大数量。如果您还没有阅读精华版C10K paper,我建议您阅读它。

您已经实现了使用单线程和单一io_service您的申请后,我建议研究线程调用io_service::run()池,然后才调查钉扎的io_service到一个特定的线程和/或CPU。在所有这三种设计的Asio文档中都包含了多个示例,并且在SO上有several questions以及更多信息。请注意,当您引入多个调用io_service::run()的线程时,您可能需要实现strand,以确保处理程序可以独占访问共享数据结构。

9

使用boost :: asio,你可以编写大约相同开发成本的单线程或多线程服务器。您可以编写单线程版本作为第一版本,然后将其转换为多线程(如果需要)。

通常,只有boost :: asio的瓶颈是epoll/kqueue反应器在互斥体中工作。所以,只有一个线程在同一时间做epoll。这可能会降低性能,因为当您有多线程服务器时,服务器会提供很多很多很小的数据包。但是,无论如何,它应该比简单的单线程服务器更快。

现在谈谈你的任务。如果你只想在连接之间传递消息 - 我认为它必须是多线程服务器。问题是系统调用(recv/send等)。一条指令对CPU来说很容易,但任何系统调用都不是非常“轻松”的操作(一切都是相对的,但相对于任务中的其他作业)。所以,单线程你会得到很大的系统调用开销,为什么我建议使用多线程方案。

此外,您可以单独使用io_service并使其成为“每线程io_service”成语。我认为这必须提供最好的性能,但它有缺点:如果io_service中的一个会得到太大的队列 - 其他线程无法帮助它,所以一些连接可能会减慢。另一方面,单个io_service - 队列溢出会导致大的锁定开销。你所能做的就是 - 做两种变体并测量带宽/延迟。实现这两种变体应该不是太困难。