当我寻找一些位置的文件,并写入数据(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尝试写一堆部门当我改变只有一个,那会降低硬件高速缓存的效率。
是否有任何磁盘的专家那里谁可以发表评论,并解释这不是我的实验结果更好? =)