确定在 Linux 中读取文件的最佳缓冲区大小



我正在编写一个C程序,它从stdin读取并写入stdout。但它缓冲数据,以便仅在读取特定数量的字节(=SIZE(后执行写入

#include<stdio.h>
#include<stdlib.h>
#define SIZE 100
int main()
{
char buf[SIZE];
int n=0;
//printf("Block size = %dn", BUFSIZ);
while( ( n = read(0, buf, sizeof(buf)) ) > 0 )
write(1, buf, n);
exit(0);
}

我在Oracle虚拟盒子(4GB RAM,2个内核(上托管的Ubuntu 18.04上运行此程序,并针对不同的缓冲区大小值测试程序。我已经将标准输入重定向到来自一个文件(其中包含动态创建的随机数(和标准输出以转到/dev/null。以下是用于运行测试的 shell 脚本:

#!/bin/bash
# $1 - step size  (bytes)
# $2 - start size (bytes)
# $3 - stop size (bytes)
echo "Changing buffer size from $2 to $3 in steps of $1, and measuring time for copying."
buff_size=$2
echo "Test Data" >testData
echo "Step Size:(doubles from previous size) Start Size:$2 Stop Size:$3" >>testData
while [ $buff_size -le $3 ]
do
echo "" >>testData
echo -n "$buff_size," >>testData
gcc -DSIZE=$buff_size copy.c    # Compile the program for cat, with new buffer size
dd bs=1000 count=1000000 </dev/urandom >testFile        #Create testFile with random data of 1GB        
(/usr/bin/time -f "t%U, t%S," ./a.out <testFile 1>/dev/null) 2>>testData
buff_size=$(($buff_size * 2))
rm -f a.out
rm -f testFile
done

我正在测量执行程序并将其制成表格所需的时间。测试运行生成以下数据:

Test Data
Step Size:(doubles from previous size) Start Size:1 Stop Size:524288
1,      5.94,   17.81,
2,      5.53,   18.37,
4,      5.35,   18.37,
8,      5.58,   18.78,
16,     5.45,   18.96,
32,     5.96,   19.81,
64,     5.60,   18.64,
128,    5.62,   17.94,
256,    5.37,   18.33,
512,    5.70,   18.45,
1024,   5.43,   17.45,
2048,   5.22,   17.95,
4096,   5.57,   18.14,
8192,   5.88,   17.39,
16384,  5.39,   18.64,
32768,  5.27,   17.78,
65536,  5.22,   17.77,
131072, 5.52,   17.70,
262144, 5.60,   17.40,
524288, 5.96,   17.99,

我没有看到用户+系统时间有任何显着变化,因为我们使用不同的块大小。但从理论上讲,随着块大小变小,相同的文件大小会生成许多系统调用,并且执行应该需要更多时间。我在Richard Stevens的《Unix Environment中的高级编程》一书中看到了类似的测试结果,该测试表明,如果copy中使用的缓冲区大小接近块大小,则用户+系统时间会显着减少。(就我而言,ext4 分区上的块大小为 4096 字节(

为什么我无法重现这些结果?我在这些测试中是否遗漏了一些因素?

您没有禁用源代码中的行#define SIZE 100,因此通过选项 (-DSIZE=1000( 的定义确实仅在此#define之上产生影响。 在我的编译器上,我在编译时收到对此(<command-line>:0:0: note: this is the location of the previous definition(的警告。

如果您注释掉#define,您应该能够修复此错误。

我想到的另一个方面:

如果您在计算机上创建一个文件并立即读取它,它将位于操作系统的磁盘缓存中(该缓存足够大以存储所有这些文件(,因此实际磁盘块大小在这里不会有太大影响。

史蒂文斯的书写于1992年,当时RAM比今天贵得多,所以也许其中的一些信息已经过时了。 我也怀疑这本书的新版本是否已经把这样的东西删掉了,因为总的来说它们仍然是真实的。

最新更新