Ich weiß, dass Festplatte (beachten Sie, ich spreche über magnetische, nicht SSDs) interne On-Disk-RAM-Caches. Dies sind in der Regel rund 64 MB. Ich versuche zu verstehen, was eine typische Lese-Pufferungsrichtlinie für diese Caches ist.Festplatte auf der Festplatte lesen Cache
Naiv, ich nahm an, dass die neuesten Lesevorgänge zwischengespeichert werden. Ich habe versucht, einen einfachen Test auf einer sekundären Festplatte, Seagate ST32000645NS HDD, mit fio und auch ein kleines Stück Code, den ich schrieb. Diese Platte ist nicht einmal montiert, daher sollte diese Tests nicht beeinträchtigt werden. Beide lesen wiederholt aus einem kleinen Bereich von Sektoren (ein paar MB), der gut in der Puffergröße auf der Platte enthalten ist. Beide Tests verwenden O_DIRECT, um die Auswirkungen des Host-BS-Puffers zu eliminieren. Da moderne Plattenschnittstellen einen GB/s-Durchsatz aufweisen und alle bis auf die anfänglichen Lesevorgänge von der Platte im Puffer auf der Platte zwischengespeichert werden sollten, erwartete ich Durchsätze von 100 MB/s. Aber ich bekomme mickrige Ergebnisse in der Größenordnung von 1 MB/s, was anzeigt, dass kein Lese-Caching auf der Festplatte durchgeführt wird. Ich habe sogar versucht, die gleiche 4KB immer wieder zu lesen und bekam immer noch ähnliche schlechte Ergebnisse.
Ich schaute in dmesg, die sagt "SD 1: 0: 0: 0: [sdb] Schreib-Cache: aktiviert, lesen Cache: aktiviert, unterstützt nicht DPO oder FUA". Es scheint also hier kein Konfigurationsproblem zu geben. Kann jemand hier etwas Licht auf das Problem mit dem Lese-Cache auf der Festplatte werfen? vielleicht sagt eine zugrunde liegende Standardkonfiguration im Treiber dem Gerät, den Lese-Cache zu ignorieren?
bearbeitet - hier sind die relevanten Teile des Codes.
fio Script-Code, den ich mehrmals in einer Reihe laufen:
[global]
bs=4k
rw=randread
random_generator=lfsr
direct=1
ioengine=libaio
iodepth=1
direct=1
[device]
filename=/dev/sdb
filesize=64M
size=64M
mein Code:
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;
}
}
Es wäre nützlicher, wenn Sie den von Ihnen geschriebenen Code anzeigen, damit wir genau verstehen, was getestet wird. Ansonsten müssen wir nur Ihre eigene Interpretation dessen, was Sie testen, beleuchten. – paddy
Danke Paddy, habe ich nach deinem Vorschlag bearbeitet. – user331398
Gibt es einen Grund, warum Sie 'O_RDWR' verwenden? Erhalten Sie eine ähnliche Leistung, wenn Sie stattdessen 'O_RDONLY' verwenden? – paddy