发生的事情在磁盘I / O的窗帘后面?(What goes on behind the curtai

2019-07-03 11:58发布

当我寻找一些位置的文件,并写入数据(20个字节)的量小,发生的事情在幕后?

我的理解

据我所知,可以写入或从磁盘读取数据的最小单位是一个扇区(传统512字节,但该标准正在发生变化)。 这意味着写20个字节我需要阅读整个行业,改变它的一些内存并把它写回磁盘。

这是我期望在无缓冲的I / O发生。 我也希望缓冲I / O做大致相同的事情,但是要聪明约缓存。 所以,我会想,如果我这样做打击当地窗外随机寻道和写入,既缓冲和无缓冲I / O应该有相似的表现......也许有缓冲出来略胜一筹。

再说,我知道这是疯了缓冲I / O只缓冲一个部门,所以我可能还期望它可怕的执行。

我的应用程序

我存储由接收了十几万点向上远程遥测技术的SCADA设备驱动程序收集的值。 还有就是文件使得每个记录是40个字节的额外数据,但需要更新时只能写20个字节的那个。

预执行基准

要检查我不需要做梦了一些出色的过度设计的解决方案,我已经运行使用几百万写入可能包含在总计200,000记录的文件随机记录的测试。 每个试验种子具有相同值的随机数发生器是公平的。 首先,我擦除该文件,并填充它的总长度(约7.6微克),然后循环数百万次,传递一个随机文件偏移量和一些数据的两个测试功能之一:

void WriteOldSchool( void *context, long offset, Data *data )
{
    int fd = (int)context;
    lseek( fd, offset, SEEK_SET );
    write( fd, (void*)data, sizeof(Data) );
}

void WriteStandard( void *context, long offset, Data *data )
{
    FILE *fp = (FILE*)context;
    fseek( fp, offset, SEEK_SET );
    fwrite( (void*)data, sizeof(Data), 1, fp );
    fflush(fp);
}

也许没有惊喜?

OldSchool方法技高一筹-受了不少。 这是快了6倍(148万对232000条记录每秒)。 为了确保我没有碰到硬件缓存,我扩大了我的数据库大小为20万条记录(763兆的文件大小),并得到了相同的结果。

你指出前明显调用fflush ,让我说,删除它没有任何效果。 我想这是因为当我寻找足够远的地方,这是我在做什么的大部分时间缓存必须承诺。

发生什么了?

在我看来,该缓冲I / O必须读取(并且可能编写所有的)一大块的文件,每当我试着写。 因为我很少考虑它的高速缓存的优势,这是非常浪费。

另外(我不知道磁盘硬件缓存的细节),如果缓冲I / O尝试写一堆部门当我改变只有一个,那会降低硬件高速缓存的效率。

是否有任何磁盘的专家那里谁可以发表评论,并解释这不是我的实验结果更好? =)

Answer 1:

的确,至少我用GNU libc的系统上,它看起来像标准输入输出被写回改变的部分之前读取4KB块。 似乎假我,但我想有人认为这是在当时是一个好主意。

我检查通过编写一个简单的C程序打开一个文件,写一个小的数据一次,并退出; 然后运行它下strace的,看看哪些系统调用它实际上触发。 在10000偏移写作,我看到了这些系统调用:

lseek(3, 8192, SEEK_SET)                = 8192
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1808) = 1808
write(3, "hello", 5)                    = 5

看来,你会想用低级别的Unix风格的坚持I / O的这个项目,是吗?



Answer 2:

C标准库函数执行额外的缓冲,并且一般被优化用于流读取,而不是随机的IO。 在我的系统, 我不遵守杂散读取詹姆夏普看见我只看到假当偏移不对齐到页面大小读取-它可能是C库总是试图保持它的IO缓冲对齐4KB或一些东西。

在你的情况,如果你正在做大量的随机读取和跨越相当小的数据集写,你很可能得到最好的使用提供pread / pwrite ,以避免使寻求系统调用,或者干脆mmap荷兰国际集团的数据集,并写入它在内存中(可能是最快的,如果你的数据集装入内存)。



文章来源: What goes on behind the curtains during disk I/O?
标签: c file-io buffer