Я знаю, что на жестком диске (обратите внимание, что речь идет о магнитных, а не в SSD), есть внутренние кеши для хранения на диске. Обычно они составляют около 64 МБ. Я пытаюсь понять, что такое типичная политика буферизации чтения для этих кешей.Кэш чтения на жестком диске на диске
Наивно, я предположил, что последние чтения кэшируются. Я попытался сделать простой тест на вторичном диске, Seagate ST32000645NS HDD, используя fio, а также небольшой фрагмент кода, который я написал. Этот диск даже не установлен, поэтому ничто не должно мешать этим тестам. Оба они многократно читаются из небольшого диапазона секторов (несколько МБ), которые хорошо содержатся в размере буфера на диске. Оба теста используют O_DIRECT для устранения эффектов буфера операционной системы. Поскольку современные дисковые интерфейсы имеют пропускную способность Gb/s, и все, кроме начальных чтений с диска, должны кэшироваться в буфере на диске, я ожидал увидеть пропускную способность 100 мб/с. Тем не менее, я получаю плохие результаты порядка 1 Мбайт/с, что указывает на то, что кэширование чтения не выполняется на диске. Я даже пытался многократно читать один и тот же 4 КБ снова и снова, и все же получил аналогичные плохие результаты.
Я посмотрел в 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;
}
}
Было бы более полезно, если вы покажете код, который вы написали, чтобы мы могли точно понять, что тестируется. В противном случае, единственное, что нам нужно пролить, - это ваша собственная интерпретация того, что вы тестируете. – paddy
Спасибо, падди, я отредактировал в соответствии с вашим предложением. – user331398
Есть ли причина, по которой вы используете 'O_RDWR'? Вы получаете схожую производительность, если вместо этого используете 'O_RDONLY'? – paddy