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 */