该程序每行打印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);
}
更新:我在Core i5-2520M上的Ubuntu 12.04 64位(具有EGLIBC 2.15)上运行它。
更新:
puts (s)
具有相同的问题。 最佳答案
您在数据传输中无法充分利用内核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] [ <=> ]
编辑:再运行3次(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] [ <=> ]
关于c - 在65KB以上的字符串上使用printf会遇到哪个瓶颈?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11852394/