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

时间:2018-05-04 13:04:33

标签: linux performance unix filesystems system-calls

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

#include<stdio.h>
#include<stdlib.h>

#define SIZE 100

int main()
{
        char buf[SIZE];
        int n=0;
        //printf("Block size = %d\n", BUFSIZ);

        while( ( n = read(0, buf, sizeof(buf)) ) > 0 )
                write(1, buf, n);
        exit(0);
}

我在托管在Oracle Virtual Box(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,

我没有看到用户+系统时间的任何显着变化,因为我们使用不同的块大小。但理论上,随着块大小变小,为相同的文件大小生成了许多系统调用,并且应该花费更多的时间来执行。我在“Unix环境下的高级编程”一书中看到了测试结果。由Richard Stevens进行的类似测试表明,如果复制中使用的缓冲区大小接近块大小,则用户+系统时间会显着减少。(在我的情况下,ext4分区的块大小为4096字节)

为什么我无法重现这些结果?我在这些测试中缺少一些因素吗?

1 个答案:

答案 0 :(得分:0)

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

如果您注释掉#define,则应该能够解决此错误。

想到的另一个方面是:

如果你在一台机器上创建一个文件并在那之后立即读取它,那么它将在OS的磁盘缓存中(它足够大以存储所有这个文件),因此实际的磁盘块大小不会有这里有很大的影响力。

史蒂文斯的书写于1992年,当时RAM比现在更昂贵,所以也许有些信息已经过时了。我也怀疑这本书的新版本已经采用了这样的东西,因为一般来说它们仍然是真的。