2016-09-20 17 views
0

ハードドライブ(メモ、私はSSDではなく磁気ディスク)は、ディスク上のRAMキャッシュが内蔵されていることを知っています。これらは通常約64MBです。私はこれらのキャッシュのための典型的な読み込みバッファリングポリシーが何であるか理解しようとしています。ハードドライブのオンディスク読み取りキャッシュ

私は最新の読み込みがキャッシュされていると考えました。セカンダリディスクであるSeagate ST32000645NS HDDで、fioと私が書いた小さなコードを使って簡単なテストを試みました。このディスクはマウントされていないため、これらのテストを妨げるものはありません。両方とも、ディスク上のバッファサイズに十分含まれている小さな範囲のセクタ(数MB)から繰り返し読み込みます。どちらのテストもO_DIRECTを使用して、ホストOSバッファの影響を排除します。現代のディスクインターフェースはGb/sのスループットを持ち、ディスクからの最初の読み取りを除いてすべてがディスク上のバッファにキャッシュされるはずなので、100s MB/sのスループットを期待していました。それでも、私は1MB/sのオーダーの結果を得ています。これは、ディスク上で読み込みキャッシュが行われていないことを示しています。私も同じ4KBを何度も何度も何度も繰り返し読み込みしようとしましたが、それでも似た結果が得られませんでした。

「sd 1:0:0:0:[sdb]書き込みキャッシュ:有効、読み取りキャッシュ:有効、DPOまたはFUAをサポートしていません」というdmesgを調べました。だからここでは構成上の問題があるようです。誰かがここでディスク上の読み取りキャッシュの問題であるかもしれないことについていくつかの光を当てることができますか?おそらく、ドライバ内のいくつかの基本的な設定は、デバイスに読み取りキャッシュを無視するように指示していますか?

編集 - ここに関連するコードがあります。私は行で複数回実行

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

あなたが書き込んだコードを表示すると、テスト対象の内容を正確に理解できるようになると、より役に立ちます。さもなければ、私達が光を当てなければならないのは、あなたがテストしているもののあなた自身の解釈だけです。 – paddy

+0

おかげで、私はあなたの提案に従って編集しました。 – user331398

+0

'O_RDWR'を使う理由はありますか?代わりに 'O_RDONLY'を使用すると、同様のパフォーマンスが得られますか? – paddy

答えて

0

通常、小型のI/OサイズにO_DIRECTを使用すると、あなたがしたいのであれば、悪い行い、大容量I/Oを発行しようとすると、エフェクトリードキャッシュが表示されます。 fioテストスクリプトまたはマイクロベンチマークコードを共有すると役立ちます。

そして、/ OダイレクトIが同期として考えることができるので、あなたは----

をうまくthis link

に記載されてhdparamで先読みをオプション----更新を設定してみてください可能性がありI/Oでは、着信I/Oを処理する前にI/Oを完了する必要があります。また、I/Oが小さいとコンテキストスイッチを作成してDMA操作用のレジスタを設定するのに多くの時間がかかります。

次のグラフは、ダイレクトI/Oテストの帯域幅を示しています。私は提供されたfioスクリプトを使用して、I/Oサイズを4KBから8MBに変更しました。直接I/Oを使用して小さなI/Oサイズを発行すると、パフォーマンスが非常に悪くなり、I/Oサイズが大きくなるとパフォーマンスも向上します。

直接I/Oのためにホストページキャッシュが機能しないため、システムは先読み機能を利用することができず、ディスク表面から、またはデバイスのディスクキャッシュからデータをフェッチしなければならず、スイッチ。

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

+0

ご協力いただきありがとうございます。関連するコードを含めるように私の投稿を編集しました(@paddyもあなたにこれを求めました)。 O_DIRECTについて - 私は小さなランダムアクセスのためにHDDの小さな読み取りでO_DIRECTが遅くなる理由を理解できます。しかし、読み込みがバッファされたデータの場合は、どうして重要なのでしょうか? – user331398

+0

NB:使用されているI/Oが非同期の場合、ダイレクトI/Oは非同期にできます。ブロックデバイスに対してioengine = libaio --direct = 1 --iodepth = 16を使用すると、Linux上で実際に動作することがわかります。終了時にfioによって報告されるキューの深さは通常1より大きくなります。 – Anon

関連する問題