C++套接字服务器 - 无法使CPU饱和

Ale*_*ack 26 c++ linux multithreading scalability boost-asio

我用C++开发了一个迷你HTTP服务器,使用boost :: asio,现在我用多个客户端加载测试它,我一直无法接近饱和CPU.我正在测试一个Amazon EC2实例,大约50%使用一个cpu,20%使用另一个cpu,其余两个闲置(根据htop).

细节:

  • 服务器为每个核心激活一个线程
  • 接收,解析,处理请求并写出响应
  • 请求是针对数据的,这些数据是从内存中读取的(此测试只读)
  • 我正在使用两台机器"加载"服务器,每台机器运行一个java应用程序,运行25个线程,发送请求
  • 我看到大约230个请求/秒吞吐量(这是应用程序请求,它由许多HTTP请求组成)

那么,我应该怎样看待改善这一结果呢?鉴于CPU大部分处于空闲状态,我希望利用这些额外的容量来获得更高的吞吐量,比如800请求/秒等等.

我有过的想法:

  • 请求非常小,并且经常在几毫秒内完成,我可以修改客户端以发送/组合更大的请求(可能使用批处理)
  • 我可以修改HTTP服务器以使用Select设计模式,这适合吗?
  • 我可以做一些分析,试图了解瓶颈是什么/是什么

cme*_*erw 44

提高:: ASIO是不是线程友好,你会希望 - 周围有升压/ ASIO /细节/ epoll的该代码epoll_reactor.hpp这意味着只有一个线程可以同时调用内核的系统调用epoll的大锁.对于非常小的请求,这会产生重大影响(意味着您只会看到大致单线程的性能).

请注意,这是对boost :: asio如何使用Linux内核工具的限制,而不一定是Linux内核本身.epoll系统调用在使用边缘触发事件时确实支持多个线程,但正确(没有过多锁定)可能非常棘手.

顺便说一句,我一直在这方面做一些工作(将全多线程边缘触发的epoll事件循环与用户调度的线程/光纤相结合),并在nginetd项目下提供了一些代码.

  • 我真的很担心这种全局锁定.它不像看起来那么大.瓶颈只能在高通量场景中出现.但是,当asio在epoll模式(linux)下运行时,它会在发出`async_*`调用时抢先尝试写或读.在高输入情况下,套接字通常可以读取,让"async_read"完全跳过epoll.你不能要求更好的网络性能. (3认同)
  • 我不认为是这样的.是的,它看起来像epoll的反应器具有的run()函数的整个持续时间范围的锁,但它暂时解除("lock.unlock();")调入epoll_wait之前并锁定epoll_wait返回("锁定后再次.锁();").不知道为什么它以这种方式完成,而不是两个范围锁. (3认同)
  • 您可以使用 BOOST_ASIO_DISABLE_THREADS 宏移除锁定。如果只有一个线程使用 io_service,那么这样做应该是安全的。 (2认同)

Mar*_*rkR 11

当您使用EC2时,所有投注均已关闭.

尝试使用真实的硬件,然后你就可以看到发生了什么.尝试在VM中进行性能测试基本上是不可能的.

我还没有弄清楚EC2有用的东西,如果有人发现,请告诉我.

  • Mark的观点是有效的:对于分析使用真实机器,或至少更受控制的环境.您可以随心所欲地部署到EC2,但要了解您正在运行VM映像,这意味着您的"空闲"CPU可能只是因为盒子上的其他租户在一段时间内获得了所有CPU.这使分析变得困难. (7认同)
  • 由于在任何给定的时间点都有几十万个(最后我听说过)EC2实例在运行,我认为很多人都会对它有用.你应该问问自己,他们知道你不知道. (6认同)
  • 因无用的切线社论而被否决。 (2认同)