C 以编程方式确定文件系统块大小

C 以编程方式确定文件系统块大小,c,linux,unix,operating-system,C,Linux,Unix,Operating System,这是我用来计算从文件中读取所需时间的代码,该时间随读取字节数的变化而变化 for(int i = 0; i < TRIALS; i++){ fd = open(argv[1], O_RDONLY); //Set the file offset to a random position on the file //But still a multiple of the current current test bloc

这是我用来计算从文件中读取所需时间的代码,该时间随读取字节数的变化而变化

for(int i = 0; i < TRIALS; i++){

            fd = open(argv[1], O_RDONLY);
            //Set the file offset to a random position on the file
            //But still a multiple of the current current test block size,
            //Simulating jumps of the given test block size
            //trying to avoid prefetch
            lseek(fd, test_block * rand() % (fs / test_block), SEEK_SET);

            //How much time takes to read `test_block` bytes
            clock_gettime(CLOCK_MONOTONIC, &ts_ini);
            ssize_t bytes_read = read(fd, buffer, test_block);
            clock_gettime(CLOCK_MONOTONIC, &ts_end);

            if(bytes_read > 0){
                accum += (((double)(ts_end.tv_sec - ts_ini.tv_sec)) + 
                    (ts_end.tv_nsec - ts_ini.tv_nsec)/NANO_TO_SEC) / TRIALS;
            }
            //Closing the file after each trial to release resources
            close(fd);
        }
我得到这个结果:

Block Size(bytes) | Avg. Time(seconds)
                4 | 0.002927567500    
                8 | 0.003120735600    
               16 | 0.004888980800    
               32 | 0.003885210600    
               64 | 0.003578379700    
              128 | 0.001272970500    
              256 | 0.004926633700    
              512 | 0.001281894000    
             1024 | 0.000243394200    
             2048 | 0.000175361100    
             4096 | 0.000001048200    
             8192 | 0.000001938000    
            16384 | 0.000003214000
根据这个结果,我假设我的系统的块大小是4096字节(这与
dumpe2fs
一致),因为在这一点上,它不需要做任何额外的操作,只需传递它从文件中获得的块,因此速度非常快,之后时间重复。(这是我的猜测)

但奇怪的是,如果我稍微修改sh脚本,在每次执行之前添加清理缓存的命令,如下所示:

echo "Block Size(bytes) | Avg. Time(seconds)"
for block in 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384
do
    echo "echo 3 > /proc/sys/vm/drop_caches" | sudo sh
    ./bin/blocksize /tmp/random_gen $block
done
然后发生这种情况:

Block Size(bytes) | Avg. Time(seconds)
                4 | 0.006217417300    
                8 | 0.003913319300    
               16 | 0.004674101500    
               32 | 0.005444699600    
               64 | 0.005125086700    
              128 | 0.004965967700    
              256 | 0.002433360800    
              512 | 0.002100266600    
             1024 | 0.002221131400    
             2048 | 0.001623008600    
             4096 | 0.001936151500    
             8192 | 0.001391976900    
            16384 | 0.001270749800
这对我来说毫无意义。为什么当我首先清理缓存时,随着测试块大小的增加,时间不断减少


很可能是在Ubuntu 14.04LTS 64位文件系统缓存和readahead上运行

文件系统看到您读取了第一个4k块,并且基于您将读取文件的其余部分的假设,它读取的数据量超过了这个4k块

尝试使用
O|u RDONLY | O_DIRECT
标志绕过文件系统缓存。如果文件系统支持直接IO,您应该会看到不同之处。您可能必须使用
valloc()/memalign()
来获得内存页对齐的缓冲区,以便将数据读入其中。

一些要点:

文件系统在一个系统上可能具有不同的块大小

当你重新阅读同一个文件时,你很可能会得到改进 因为缓存。大多数现代高清设备都有板载缓存,操作系统也有缓存

POSIX提供了获取文件系统信息(如块大小)的标准方法:stavfs系统调用。 与stat一样,它也返回一个结构。这显示了我的系统上的一个,每个实现可能有一些额外/不同的字段,因此您的字段可能不同:

 u_long      f_bsize;             /* preferred file system block size */
 u_long      f_frsize;            /* fundamental filesystem block
                                     (size if supported) */
 fsblkcnt_t  f_blocks;            /* total # of blocks on file system
                                     in units of f_frsize */
 fsblkcnt_t  f_bfree;             /* total # of free blocks */
 fsblkcnt_t  f_bavail;            /* # of free blocks avail to
                                     non-privileged user */
 fsfilcnt_t  f_files;             /* total # of file nodes (inodes) */
 fsfilcnt_t  f_ffree;             /* total # of free file nodes */
 fsfilcnt_t  f_favail;            /* # of inodes avail to
                                     non-privileged user*/
 u_long      f_fsid;              /* file system id (dev for now) */
 char        f_basetype[FSTYPSZ]; /* target fs type name,
                                     null-terminated */
 u_long      f_flag;              /* bit mask of flags */
 u_long      f_namemax;           /* maximum file name length */
 char        f_fstr[32];          /* file system specific string */
 u_long      f_filler[16];        /* reserved for future expansion */

不确定这是否如您所期望的那样有效。您的磁盘驱动器是否有大量未考虑的缓存?您可能会通过重复读取相同扇区来初始化硬件的缓存算法?块大小由设备决定。
 u_long      f_bsize;             /* preferred file system block size */
 u_long      f_frsize;            /* fundamental filesystem block
                                     (size if supported) */
 fsblkcnt_t  f_blocks;            /* total # of blocks on file system
                                     in units of f_frsize */
 fsblkcnt_t  f_bfree;             /* total # of free blocks */
 fsblkcnt_t  f_bavail;            /* # of free blocks avail to
                                     non-privileged user */
 fsfilcnt_t  f_files;             /* total # of file nodes (inodes) */
 fsfilcnt_t  f_ffree;             /* total # of free file nodes */
 fsfilcnt_t  f_favail;            /* # of inodes avail to
                                     non-privileged user*/
 u_long      f_fsid;              /* file system id (dev for now) */
 char        f_basetype[FSTYPSZ]; /* target fs type name,
                                     null-terminated */
 u_long      f_flag;              /* bit mask of flags */
 u_long      f_namemax;           /* maximum file name length */
 char        f_fstr[32];          /* file system specific string */
 u_long      f_filler[16];        /* reserved for future expansion */