11

该程序每行打印 65k 字节。

我测量吞吐量./a.out | pv >/dev/null并得到大约 3 GB/s。

一旦我将线路长度更改为 70k,吞吐量就会下降到 ~ 1 GB/s。

我在这里遇到了哪个瓶颈(CPU 缓存、libc 特质等) ?

#include <stdio.h>
#include <string.h>

#define LEN 65000     // high throughput
// #define LEN 70000  // low throughput

int main ()
{
  char s[LEN]; memset(s, 'a', LEN-1); s[LEN-1] = '\0';

  while (1)
    printf ("%s\n", s);
}

更新:我在具有 EGLIBC 2.15 的 Ubuntu 12.04 64 位和 Core i5-2520M 上运行它。

更新: puts (s)有同样的问题。

4

1 回答 1

6

您在数据传输中未充分利用内核 I/O 缓冲区。如果我们假设 64KB 是内核 I/O 缓冲区大小,那么 70000 写入将在写入 64KB 后阻塞。当它耗尽时,剩余的 4KB + 更改将写入 I/O 缓冲区。pv最终执行两次读取以读取70000传输的每个字节,由于缓冲区利用率不佳,导致正常吞吐量的一半左右。写入期间 I/O 的停顿可能弥补了其余部分。

您可以为 指定较小的读取大小pv,这将通过增加每个时间片传输的平均字节数来增加您的吞吐量。平均而言,写入效率更高,并保持读取缓冲区满。

$ ./a.out | pv -B 70000 > /dev/null
9.25GB 0:00:09 [1.01GB/s] [        <=>                                        ]

$ ./a.out | pv -B 30k > /dev/null
9.01GB 0:00:05 [1.83GB/s] [    <=>                                            ]

编辑:另外三个运行(2.7GHz 核心 i7)

$ ./a.out | pv -B 16k > /dev/null
  15GB 0:00:08 [1.95GB/s] [       <=>                                         ]

$ ./a.out | pv -B 16k > /dev/null
 9.3GB 0:00:05 [1.85GB/s] [    <=>                                            ]

$ ./a.out | pv -B 16k > /dev/null
19.2GB 0:00:11 [1.82GB/s] [          <=>                                      ]
于 2012-08-07T19:36:30.453 回答