【问题标题】:Boost: multithread performance, reuse of threads/sockets提升:多线程性能,线程/套接字的重用
【发布时间】:2015-01-20 13:11:23
【问题描述】:

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

我正在尝试为我们的分布式 DAQ 系统实现“单线程一连接”方案。我在 Linux 平台上将 Boost 用于线程 (thread_group),将 ASIO 用于套接字。

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

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

我们的要求是线程应该以尽可能短的时间延迟读取它们各自的套接字连接。在阅读了有关 C10K and this post 的信息后,我希望每个线程每秒都能轻松处理至少 1K 的 MTU 大小的数据包。

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

我的问题是:

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

【问题讨论】:

  • 荣誉 +1 是为了实际进行测量。你缺乏的任何理解都会随着这种调查性的心态而迅速到来。如果你保持这个习惯,你就不会陷入可扩展性陷阱,以为你已经看到了这一切:)

标签: multithreading sockets boost c10k


【解决方案1】:

320 个线程在资源方面是巨大的变化,但调度可能会带来问题。

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

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


Q.阅读了 C10K 和这篇文章后,我预计每个线程每秒都能轻松处理至少 1K 的 MTU 大小的数据包

是的。单个线程可以轻松维持(在大多数系统上)。 但是显然,如果您有数百个线程尝试相同的线程,竞争一个物理核心,那么这将不再正确。

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


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

好消息是 Boost Asio 使得使用单个线程(或有限的线程池)从其服务队列中为异步任务提供服务变得非常容易。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多