2011年2月2日水曜日

zfsのprefetchは無効にすべきか

結論:無効にしました。

メモリ4GB以下の環境では、prefetchは無駄読みが多いので無効にすべしとの話を散見します。
かなり大容量メモリの場合でも意味がないとのことでした。
では8GBの場合は、というと、あまり具体的な言及がないようなので、簡単にベンチしてみました。


■事前準備
kfs01# dd if=/dev/random of=/kfs01/DVD/rand.dat bs=1M count=8000
kfs01# dd if=/dev/random of=/kfs01/DVD/rand2.dat bs=1M count=8000
kfs01# dd if=/dev/random of=/kfs01/DVD/rand3.dat bs=1M count=8000
※compressionはoffです

■vfs.zfs.prefetch_disable=1
kfs01# dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M

8388608000 bytes transferred in 61.856323 secs (135614398 bytes/sec)

kfs01# dd if=/kfs01/DVD/rand.dat of=/dev/null bs=512

8388608000 bytes transferred in 126.849035 secs (66130641 bytes/sec)

○同じファイルに10秒差で3プロセス同時アクセス
kfs01# sleep 10; dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &
kfs01# sleep 20; dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &
kfs01# sleep 30; dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &

8388608000 bytes transferred in 118.090073 secs (71035675 bytes/sec)
8388608000 bytes transferred in 108.089322 secs (77608110 bytes/sec)
8388608000 bytes transferred in 134.888056 secs (62189405 bytes/sec)

○別のファイルに3プロセス同時アクセス
kfs01# dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &
kfs01# dd if=/kfs01/DVD/rand2.dat of=/dev/null bs=1M &
kfs01# dd if=/kfs01/DVD/rand3.dat of=/dev/null bs=1M &

8388608000 bytes transferred in 252.801162 secs (33182632 bytes/sec)
8388608000 bytes transferred in 279.368155 secs (30027073 bytes/sec)
8388608000 bytes transferred in 285.504720 secs (29381679 bytes/sec)

■vfs.zfs.prefetch_disable=0
kfs01# dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M

8388608000 bytes transferred in 78.085995 secs (107427817 bytes/sec)

kfs01# dd if=/kfs01/DVD/rand.dat of=/dev/null bs=512

8388608000 bytes transferred in 87.117275 secs (96290982 bytes/sec)

○同じファイルに10秒差で3プロセス同時アクセス
kfs01# sleep 10; dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &
kfs01# sleep 20; dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &
kfs01# sleep 30; dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &

8388608000 bytes transferred in 210.107980 secs (39925223 bytes/sec)
8388608000 bytes transferred in 200.080233 secs (41926221 bytes/sec)
8388608000 bytes transferred in 185.853389 secs (45135620 bytes/sec)

○別のファイルに3プロセス同時アクセス
kfs01# dd if=/kfs01/DVD/rand.dat of=/dev/null bs=1M &
kfs01# dd if=/kfs01/DVD/rand2.dat of=/dev/null bs=1M &
kfs01# dd if=/kfs01/DVD/rand3.dat of=/dev/null bs=1M &

8388608000 bytes transferred in 329.962485 secs (25422914 bytes/sec)
8388608000 bytes transferred in 330.320616 secs (25395351 bytes/sec)
8388608000 bytes transferred in 332.796445 secs (25206423 bytes/sec)

■結論
ブロックサイズの小さなシーケンシャルリードは、prefetch有効のほうが速かったです。
シーケンシャルでもブロックサイズが大きいとprefetch無効のほうが速かったです。
このへんの挙動は、おおむね想定の範囲内かなと思いました。

sambaのout速度は、あんまり変わらなかったです。
sambaには一度に読む量の設定があった気がするので、設定依存かも知れません。

ddを3本同時に走らせた場合、prefetch無効のほうが速かったです。これは意外。
てっきりprefetchで先読みしてあげればIO待ちが軽減されるかと思ったのですが、速度が出てない。
ただいずれにしても、パフォーマンスは思ったほど落ちなかったようです。NCQかZFSのおかげかわかりませんが。

で、結局どうするかというと、
ブロックサイズの細かいファイルアクセスが続くような場合ですと
prefetch有効のほうがいいみたいですが、それ以外の場合は無効のほうがいいみたいですね。

ということはprefetchはホームユースのストレージサーバでは、あんまりメリットがない気がします。
でっかいファイルをシーケンシャルにドンドコ読むか、細かいファイルを個別に開いて編集するか、がほとんどかなと。

ウェブのストレージとしてもARC&L2ARCやクライアントサイドでのキャッシュなど踏まえますと
たいていの場合は、全然意味がない機能かも知れませんね?

唯一、システム起動ディスク用途としてはONのほうがいいかも知れません?
けどzvolの挙動はzfsとは異なるようなので、また改めて研究が必要だなぁ、と思います。

というわけで、追加研究の時間はなさげなので、prefetch無効で運用することにします。