テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(writeboost report) ライトブーストにリードキャッシュを実装する検討

ライトブーストはライトだけをキャッシュする. そうしている根拠は, リードなんかキャッシュしても意味ないと思うからであるが, それでもリードをキャッシュ出来ると多少はありがたいだろうとは思う.

これが出来ると, ライトもリードも, 同じキャッシュの中にログ上にすらーっと並ぶ.

何をしたいかというと, HDDからリードしたデータを, ライトのパスに送り込んで, キャッシュに書くのだが, これが絵を描くように簡単には行かない. ごくごく稀ではあるが, ライトのパスに送り込んだデータがすでに古くなってる可能性があるからだ. タイミングの差で, RAMバッファに新しく書き込んだデータを古いデータで上書きしてしまう可能性がある. もちろん, ロックをガチガチにとれば実装は出来るが, ライトブーストをそんなゴミにするわけにはいかない. 当然ながら, ライトオンリーで動いている時と同等のオーバーヘッドでリードもキャッシュ出来ることが条件だ.

一番簡単には, リードからのライトがキャッシュヒットになる場合は無視するでいいのだが, さてどうやったらそんな実装が出来るのかがよくわからない. bioの拡張データにbitを持たせるとかわけの分からない実装はあるだろうが, うまくいく感じがしない.

ライトパスの構造は簡単にいうと以下のような感じである.

  1. mutex_lock
  2. キャッシュヒット判定をする.
  3. ライトをRAMバッファに流し込む
  4. mutex_unlock

リードに成功したデータをendioの延長で溜めておいて, しきい値が溜まった時点で, この操作に強引に流し込む(generic_make_requestのパスは通さない. Ackする必要もないから). この時, 2でキャッシュヒットである場合は無視することにする.

ライトオンリーである場合からのオーバーヘッドは, この溜まったデータをmutex中に流しこむ間ずっとmutexをとり続けることだが, この処理自体はメモリ上の処理であり, ディスクの時間オーダに比べるとはるかに小さいので無視出来る. そしてもともと, HDDからのリード量が多いわけはないのだから, この排他時間はなお短くなる.

この実装の問題点は, キャッシュヒットした時に無視するコードを書かなければならないことだ. 実装の一例は, キャッシュヒットしたら無視するモードをつけることだが, こういうモードを増やすのはあんまり好ましくない. 特に, 特定用途だけのフラグとか, きな臭いにもほどがある.

と, バドワイザーを飲みながら悩んではみたが, たぶんやらんだろう. 相当暇ならやるかもしれないというぐらいか.

(追記)

  • リードキャッシュしたものは, クリーンだからライトバックする必要はない.
  • パーシャルリードは無視した方が良いかも知れない. 完全には読めない. 少なくとも, 4KBだけをキャッシュしても現実的には十分だし, バグを少なくする点で優れると思う. また, 4KBしかキャッシュしないと決めつけられるならば, コードパスに工夫が出来る可能性がある.

(追記)

やっぱやるか. しかしSSDが即死するのではないか感はある. 却ってリードヒット落ちるのではないか感もある.

(追記)

HDDからのリードAckは大体順番どおり届くだろうから, キャッシュするためのしきい値も実装出来るな. 例えば256KB以上連続なリードはキャッシュしない