pic*_*c11 11 c++ linux boost epoll boost-asio
我正在实现需要维护非常大量(100K或更多)长期连接的自定义服务器.服务器只是在套接字之间传递消息,它不会进行任何严肃的数据处理.消息很小,但其中很多都是每秒接收/发送的.减少延迟是目标之一.我意识到使用多个内核不会提高性能,因此我决定通过调用run_one或者对象poll方法在单个线程中运行服务器io_service.无论如何,多线程服务器将更难实现.
可能存在哪些瓶颈?系统调用,带宽,完成队列/事件多路分解?我怀疑调度处理程序可能需要锁定(这是由asio库在内部完成的).是否可以在boost.asio中禁用偶然队列锁定(或任何其他锁定)?
编辑:相关问题.多线程的系统调用性能是否有所改善?我的感觉是,因为系统调用是内核原子/同步的,所以添加更多线程不会提高速度.
Sam*_*ler 16
您可能想在几年前阅读我的问题,在第一次调查Boost.Asio的可扩展性时,我在开发Blue Gene/Q超级计算机的系统软件时问过它.
扩展到100k或更多连接应该不是问题,但您需要了解明显的资源限制,例如打开文件描述符的最大数量.如果您还没有阅读开创性的C10K论文,我建议您阅读.
在使用单个线程和单个线程实现应用程序之后io_service,我建议调查一个线程池调用io_service::run(),然后再调查固定io_service到特定线程和/或cpu.所有这三个设计的Asio文档中都包含多个示例,并且有关SO的几个问题包含更多信息.请注意,当您引入多个线程调用时,io_service::run()您可能需要实现strands以确保处理程序具有对共享数据结构的独占访问权.
使用boost :: asio,您可以以相同的开发成本编写单线程或多线程服务器.您可以将单线程版本编写为第一个版本,然后根据需要将其转换为多线程版本.
通常,只有boost :: asio的瓶颈是epoll/kqueue反应器在互斥锁中工作.所以,只有一个线程同时在做epoll.如果您拥有多线程服务器,这可能会降低性能,该服务器提供大量非常小的数据包.但是,无论如何,它应该比简单的单线程服务器更快.
现在关于你的任务.如果你只想在连接之间传递消息 - 我认为它必须是多线程服务器.问题是系统调用(recv/send等).一个指令很容易想到CPU,但任何系统调用都不是非常"轻"的操作(一切都是相对的,但相对于你的任务中的其他工作).因此,使用单线程,您将获得大的系统调用开销,这就是为什么我建议使用多线程方案.
此外,您可以将io_service分开并使其成为"每个线程的io_service"惯用法.我认为这必须提供最佳性能,但它有一个缺点:如果io_service中的一个会得到太大的队列 - 其他线程将无法帮助它,所以一些连接可能会减速.另一方面,使用单个io_service - 队列溢出会导致大的锁定开销.所有你能做的 - 做两种变体并测量带宽/延迟.实现这两种变体应该不太难.