这是我用来计算读取不同字节数的文件所需时间的代码。
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);
}
现在,如果我用这个小 shell 脚本运行这个程序:
echo "Block Size(bytes) | Avg. Time(seconds)"
for block in 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384
do
./bin/blocksize /tmp/random_gen $block
done
我得到这个结果:
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
有了这个结果,我假设我的系统的 block 大小是 4096 字节(这与 dumpe2fs
一致),因为在这一点上它不需要做任何额外的操作,只是传递它从文件中获得的 block ,因此非常快,然后时间重复。 (这是我的猜测)
但这是奇怪的部分,如果我稍微修改一下 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
这对我来说没有任何意义。为什么我先清理缓存后,随着测试 block 大小的增加,时间会越来越少?
在 Ubuntu 14.04LTS 64 位上运行
最佳答案
几点:
文件系统在一个系统上可能有不同的 block 大小。
当重新读取同一个文件时,您很可能会获得改进的时间 因为缓存。大多数现代高清设备都有板载缓存,操作系统也有缓存。
POSIX 提供了一种获取文件系统信息(如 block 大小)的标准方法: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 */
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html
关于c - 以编程方式确定文件系统 block 大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29636876/