【发布时间】:2017-01-27 20:36:06
【问题描述】:
我知道硬盘驱动器(注意,我说的是磁性驱动器,而不是 SSD)具有内部磁盘 RAM 缓存。这些通常约为 64MB。我试图了解这些缓存的典型读取缓冲策略是什么。
天真地,我假设最新的读取被缓存了。我尝试使用 fio 以及我编写的一小段代码在辅助磁盘 Seagate ST32000645NS HDD 上进行简单测试。该磁盘甚至没有安装,因此不会干扰这些测试。两者都从磁盘缓冲区大小中包含的小范围扇区(几 MB)重复读取。两个测试都使用 O_DIRECT,以消除主机操作系统缓冲区的影响。由于现代磁盘接口具有 Gb/s 吞吐量,并且除了从磁盘的初始读取之外的所有内容都应该缓存在磁盘缓冲区中,我预计会看到 100s MB/s 的吞吐量。然而,我得到的结果只有 1MB/s,这表明磁盘上没有进行读取缓存。我什至尝试一遍又一遍地重复读取相同的 4KB,但仍然得到类似的糟糕结果。
我查看了 dmesg,上面写着“sd 1:0:0:0: [sdb] 写入缓存:启用,读取缓存:启用,不支持 DPO 或 FUA”。所以这里似乎没有配置问题。谁能在这里阐明磁盘读取缓存可能存在的问题?也许驱动程序中的一些底层默认配置告诉设备忽略读取缓存?
已编辑 - 这是相关的代码。
我连续多次运行的fio脚本代码:
[global]
bs=4k
rw=randread
random_generator=lfsr
direct=1
ioengine=libaio
iodepth=1
direct=1
[device]
filename=/dev/sdb
filesize=64M
size=64M
我的代码:
char name[20] = "/dev/sdb";
int fd = open(name, O_RDWR | O_DIRECT);
if (fd < 0){
printf("failed openning %s. errno %d\n", name, errno);
return -1;
}
int pagesize=getpagesize();
printf("pagesize %d\n", pagesize);
char* realbuff=malloc(4096+pagesize);
char* buf=((((int unsigned)realbuff+pagesize-1)/pagesize)*pagesize);
int res, off, total_reads = 100000;
for (i=0; i<total_reads;i++){
off = 0;
res = lseek(fd, off, SEEK_SET);
if (res != off){
printf("seek res %d, expected %d\n. i %d errno %d", res, off, i, errno);
close(fd);
return -1;
}
res = read(fd, buf, pagesize);
if (res != pagesize){
printf("read only %d bytes, expected %d\n. i %d errno %d", res, pagesize, i, errno);
close(fd);
return -1;
}
}
【问题讨论】:
-
你有什么理由使用
O_RDWR吗?如果你改用O_RDONLY,你会得到类似的性能吗? -
与 O_RDONLY 没有区别。我计划在将数据读取到磁盘之前先写入数据,所以我使用了 O_RDWR。