提升:多线程性能,线程/套接字的重用

时间:2015-01-20 13:11:24

标签: multithreading sockets boost c10k

我首先描述我的任务,然后在下面提出我的问题。

我正在尝试实现"一个线程一个连接"我们的分布式DAQ系统的方案。我在Linux平台上使用了Boost for threads(thread_group)和ASIO for socket。

我们有320个联网的DAQ模块。大约每0.25ms一次,大约一半将生成一个数据包(大小小于标准MTU)并发送到Linux服务器。每个模块都有自己的长寿命TCP连接到服务器上的专用端口。也就是说,服务器端应用程序在1Gbe NIC上运行320个线程320 tcp同步接收器,8个CPU核心

320个线程不必对传入数据进行任何计算 - 只接收数据,生成并添加时间戳并将数据存储在线程拥有的内存中。套接字都是同步的,因此阻止没有传入数据的线程。插座在运行期间保持打开状态。

我们的要求是线程应该尽可能少地延迟读取各自的套接字连接。阅读了有关C10K and this post 的信息后,我预计每个线程每秒都会轻松处理相当于至少1K MTU大小的数据包。

我的问题是这个:我首先通过在服务器上触发时间同步数据来测试系统(不同套接字上的传入数据相隔不到几微秒)。当数据包的数量非常小(小于10)时,我发现线程时间戳相隔几微秒。 但是,如果超过10,则时间戳的传播时间间隔为0.7秒。

我的问题是:

  1. 我是否完全误解了C10K问题并搞砸了实施?与C10K
  2. 相比,320确实显得微不足道
  3. 任何有关出错的提示?
  4. 这真的是重用线程和/或套接字的情况吗? (我真的不知道如何在我的情况下实现重用,所以任何解释都会受到赞赏。)

1 个答案:

答案 0 :(得分:1)

320个线程在资源方面发生了变化,但调度可能会带来问题。

320 * 0.25 =每秒80个请求,这意味着至少有80个上下文切换,因为您决定必须在线程上建立每个连接。

我只是建议:不要这样做。众所周知,每个连接的线程不能扩展。它几乎总是意味着对任何共享资源的进一步锁定争用(假设所有响应都不是完全无状态的。)


  

问。在阅读了有关C10K和这篇文章之后,我预计每个线程每秒都会轻松处理相当于至少1K的MTU大小数据包

是。单个线程可以轻松维持(在大多数系统上)。 这已不再适用,显然,如果您有数百个线程尝试相同,则竞争物理核心。

因此,为了获得最大吞吐量和低延迟,拥有比可用(!)物理内核更多的线程几乎没有用。


  

问。这是否真的可以重用线程和/或套接字? (我真的不知道如何在我的情况下实现重用,所以任何解释都会受到赞赏。)

好消息是,Boost Asio可以很容易地使用单个线程(或有限的线程池)从其服务队列中为异步任务提供服务。

也就是说,假设您已经使用了*_async版本的ASIO API函数。

我认为绝大多数 - 如果不是全部 - 异步IO的Boost Asio示例显示了如何仅在有限数量的线程上运行服务。