![read() 随机打开 O_DIRECT 标志的文件,在 32 MB 文件大小上会严重影响性能吗?](https://linux22.com/image/100019/read()%20%E9%9A%8F%E6%9C%BA%E6%89%93%E5%BC%80%20O_DIRECT%20%E6%A0%87%E5%BF%97%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%8C%E5%9C%A8%2032%20MB%20%E6%96%87%E4%BB%B6%E5%A4%A7%E5%B0%8F%E4%B8%8A%E4%BC%9A%E4%B8%A5%E9%87%8D%E5%BD%B1%E5%93%8D%E6%80%A7%E8%83%BD%E5%90%97%EF%BC%9F.png)
我正在运行绕过页面缓存的 HDD 读取基准测试。我已经设置了 O_DIRECT 标志并修改了我的内存。此函数尝试在文件中随机读取(使用 lseek64())。我得到的数据在某个点(32 MB)之前看起来都很好。请看下面的数据(平均值): 我特别想知道为什么我在32MB之后会有这么大的跳跃?我使用 Ubuntu 16.04 文件系统 ext4。
我真的很感激对此的一些帮助。谢谢。
KB TIME
32 11.2452
64 22.3882
128 45.3915
256 89.6025
512 12.655
1024 402.332
2048 759.456
4096 1512.83
8192 2999.54
16384 5988.16
32768 **85358.8**
double readFileRan(std::string name, unsigned long bytes) {
Time t;
int ID = open(name.c_str(), O_RDONLY | O_DIRECT);
sync();
if ( ID == -1) {
std::cout << "can't open input file!" << std::endl;
return 0;
}
unsigned long reads = bytes / 512;
std::vector<unsigned long> offsets;
for(unsigned long i = 0; i < reads; i++) {
offsets.push_back((rand() % reads) * 512);
}
int BLKSIZE = 512;
char* sector = (char*)memalign(BLKSIZE, BLKSIZE); //size of physical sector
unsigned long numRead = 0;
unsigned long i = 0;
off64_t result = 10;
unsigned long long start = t.start();
while(i <= reads) {
result = lseek64(ID, offsets[i] ,SEEK_SET);
numRead = read(ID, sector, 512);
i = i + 1;
}
unsigned long long end = t.end();
close(ID);
unsigned long long total = end - start;
double mili = t.convertCyclesToSec(total);
std::cout << mili << std::endl;
return mili;
}
答案1
读取扇区的时间取决于尝试读取时驱动器的旋转角度,并且您的样本量太小,无法避免此随机过程的统计波动。每个扇区平均只读一次。当bytes
很大并且您要采集大量样本时,这很好,但当bytes
很小时,那就不太好了。为了获得更有趣的数据,您应该始终读取固定数量的扇区,而与 的大小无关bytes
。
在某些时候,当超过柱面大小时,访问时间预计会出现跳跃bytes
,并且磁头必须从磁道移动到磁道,而不是仅仅等待正确的扇区飞过(这也需要时间,但时间较少)。但是,当读取原始分区而不是通过文件系统(可以自由地将文件扇区非线性映射到设备扇区)时,可以更好地看到这种效果。
当然,现代磁盘的柱面尺寸是可变的,因为与靠近主轴的较短内磁道相比,较长的外磁道可以容纳更多的扇区。
尝试测量所有这些会变得更加复杂,因为您可能在磁盘本身上有一个小的内存缓存,并且不能单独使用O_DIRECT
.