我正在实现自定义服务器,需要保持非常大的数量(100K或更多)的长期连接。 服务器只是在套接字之间传递消息,并没有做任何严肃的数据处理。 消息很小,但是其中许多消息都是每秒收到/发送的。 减less延迟是目标之一。 我意识到使用多核并不会提高性能,因此我决定通过调用io_service对象的run_one或poll方法在单个线程中运行服务器。 无论如何,multithreading服务器将更难实施。
什么是可能的瓶颈? 系统调用,带宽,完成队列/事件解复用? 我怀疑调度处理程序可能需要locking(这是由asio库内部完成)。 是否有可能禁用boost.asio甚至队列locking(或任何其他locking)?
编辑:相关的问题。 multithreading的系统调用性能是否会提高? 我的感觉是,因为系统调用是由内核primefaces/同步添加更多的线程不会提高速度。
在socket.close被调用之后,socket.read_some需要一段时间才能返回
TCP套接字发送较less的字节数
ipv4和ipv6从任何有效的地址
C ++使用Windows命名pipe道
当一个async_write()操作永远不会结束并且涉及到一个链时会发生什么?
boost :: asio如何实现定时数据包发送function?
如何正确使用boost :: asio在multithreading程序中处理fork()?
升asio async_accept在Windows下工作,但在FreeBSD下失败。 怎么了?
ConnectNamedPipe和asio重叠ptr
如何指定一个特定的网卡用于用c ++编写的应用程序(boost asio)
你可能想要阅读我几年前的问题,在开发Blue Gene / Q超级计算机的系统软件的时候,我首先调查了Boost.Asio的可扩展性。
缩放到100k或更多的连接应该不成问题,但您需要了解明显的资源限制,例如打开的文件描述符的最大数目。 如果您还没有阅读开创性的C10K论文 ,我建议您阅读。
在使用单线程和单个io_service实现应用程序之后,我建议调查调用io_service::run()的线程池,然后调查将io_service固定到特定的线程和/或cpu。 Asio文档中包含了所有这三种设计的多个示例,以及关于SO的几个问题以及更多信息。 请注意,当您引入多个线程调用io_service::run()您可能需要实现strand以确保处理程序具有对共享数据结构的独占访问权限。
使用boost :: asio,你可以编写单线程或者多线程的服务器,大约花费相同的开发成本。 您可以将单线程版本编写为第一个版本,然后根据需要将其转换为多线程。
通常,boost :: asio的瓶颈只是epoll / kqueue反应器在互斥体中工作。 所以,只有一个线程同时在做epoll。 这可以降低性能,当你有多线程服务器,它服务很多很多很小的数据包。 但是,反正它应该比简单的单线程服务器更快。
现在关于你的任务。 如果你只想在连接之间传递消息 – 我认为它必须是多线程服务器。 问题是系统调用(recv /发送等)。 一个指令很容易被认为是为cpu做的,但是任何系统调用都不是很“轻”的操作(一切都是相对的,但相对于你的任务中的其他任务)。 所以,单线程你会得到很大的系统调用开销,为什么我建议使用多线程方案。
此外,你可以分开io_service,并使其作为“每线程io_service”成语。 我认为这必须提供最好的性能,但是它有一个缺点:如果io_service中的一个会得到太大的队列 – 其他线程不会帮助它,所以一些连接可能会减慢。 另一方面,单个io_service – 队列溢出会导致很大的锁定开销。 所有你能做的 – 做这两个变种,并衡量带宽/延迟。 实现这两个变体应该不是太困难。