使用printf打击哪个瓶颈> 65KB字符串?

时间:2012-08-07 19:01:03

标签: c performance caching printf benchmarking

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

我使用./a.out | pv >/dev/null测量吞吐量并获得大约3 GB / s的速度。

只要将线路长度更改为70k,吞吐量就会降至~1 GB / s。

哪个瓶颈(CPU缓存,libc idiosynchrasy等)我在这里?

#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);
}

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

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

1 个答案:

答案 0 :(得分:6)

您正在使用数据传输中的内核I / O缓冲区。如果我们假设64KB是内核I / O缓冲区大小,那么在写入64KB之后将会阻塞70000写入。当它耗尽时,剩余的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] [          <=>                                      ]