2016-09-20 6 views
0

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; 
    } 
} 
+0

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

+0

Danke Paddy, habe ich nach deinem Vorschlag bearbeitet. – user331398

+0

Gibt es einen Grund, warum Sie 'O_RDWR' verwenden? Erhalten Sie eine ähnliche Leistung, wenn Sie stattdessen 'O_RDONLY' verwenden? – paddy

Antwort

0

Regel mit O_DIRECT auf kleine E/A-Größen führt schlecht, so dass, wenn Sie wollen Um den Effekt Lese-Cache zu sehen, versuche einen großen I/O auszugeben. Es wäre hilfreich, das Testskript fio oder Ihren Micro-Benchmark-Code zu teilen, um Ihnen zu helfen.

Und man könnte versuchen, in hdparam Read-Ahead-Option Einstellung, die gut in this link dokumentiert

---- ---- aktualisiert

Da eine direkte I/O kann als Synchron gedacht werden E/A muss die E/A abgeschlossen sein, bevor eingehende E/A verarbeitet werden. Und kleine I/Os würden viel Zeit benötigen, um Kontextwechsel vorzunehmen und Register für DMA-Operationen einzurichten.

Die folgende Grafik zeigt die Bandbreite des direkten I/O-Testfio-Skripts. Ich habe die I/O-Größen von 4KB auf 8MB mit dem mitgelieferten fio-Skript geändert. Es zeigt, dass die Ausgabe kleiner E/A-Größen unter Verwendung von Direct I/O sehr schlechte Leistung zeigt. Mit zunehmender I/O-Größe steigt auch die Leistung.

Da der Host-Seitencache aufgrund direkter E/A nicht funktioniert, kann das System die Readahead-Funktion nicht nutzen und die Daten müssen von der Festplattenoberfläche oder vom Festplattencache auf dem Gerät abgerufen werden Schalter.

direct I/O: file size 64MB, I/O size from 4 KB to 8MB

+0

Danke für Ihre Hilfsbereitschaft. Ich habe meinen Beitrag bearbeitet, um die relevanten Teile des Codes zu enthalten (@paddy, die Sie auch danach gefragt haben). Wie für O_DIRECT - Ich kann verstehen, warum O_DIRECT für kleine Lesevorgänge auf einer Festplatte für kleine zufällige Zugriffe langsam ist. Aber wenn das Lesen für gepufferte Daten ist, warum sollte es wichtig sein? – user331398

+0

Hinweis: Direkte E/A kann asynchron in fio sein, wenn die verwendete io-Engine asynchron ist. Sie können dies unter Linux in Aktion sehen, wenn Sie ioengine = libaio --direct = 1 --iodepth = 16 für ein Blockdevice verwenden - die von fio gemeldete Warteschlangentiefe ist normalerweise größer als 1. – Anon