読者です 読者をやめる 読者になる 読者になる

テストステ論

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

(writeboost report) リードキャッシュスレッショルドの実装

先日の記事で, ライトブーストにリードキャッシュを実装したことを報告した. Todoとして, スレッショルドの実装を挙げた. 今回はそのスレッショルドの実装について説明する.

(writeboost report) リードキャッシングの説明 - テストステ論

以下が前回同様, シーケンシャルライトを続けて定常状態に落ちた時のsarである. バッキングデバイス(252-32)からキャッシュデバイス(252-16)へのステージングが行われていないことが分かる. 以前は, リード量と同量がキャッシュデバイスにライトされていた.

18:16:05          DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz     await     svctm     %util
18:16:06     dev252-0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
18:16:06    dev252-16      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
18:16:06    dev252-32   6445.00  51552.00      0.00      8.00      2.66      0.41      0.14     91.00
18:16:06     dev251-0   6443.00  51544.00      0.00      8.00      2.67      0.41      0.14     92.00
18:16:06     dev251-1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
18:16:06     dev251-2      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
18:16:06     dev251-3      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
18:16:06     dev251-4   6443.00  51544.00      0.00      8.00      3.04      0.47      0.14     92.00

実装は, シーケンシャルと思った時に, 該当するcellをキャンセルするだけである. コードを見れば分かるだろう. thresholdより多く連続したリードが来た場合, それより連続カウント(seqcount)分をキャンセルする. 一旦連続状態に入った場合は(over_threshold=true), 一個一個キャンセルする. 連続でなくなった場合は, 状態をクリアしてやり直す. という, 局所に閉じた簡単な状態制御である.

  • この方式のよい点は, split前の実際のbioより大きなサイズをthresholdとして指定したとしても(バッキングデバイスが受け付けられる最大のsector長は上限があるため, 一般のブロックレイヤでスプリットされる), bioに跨って連続をトラック出来るということ.
  • 悪い点は, 複数スレッドが同時に読み込んだ時はlast_adressが食い違いになってしまい, 連続が追えなくなること. 実はこの挙動についてはたぶんそうなるだろうと思ってるだけで確かめたわけではないので, 今度, ddを複数プロセスから打って確かめようと思う. それでもなお一切のステージングが行われないのであれば, 上位が出したbioのスプリットは上位の粒度で行われることになり, 並行処理されていないことになる. たぶんだが, 下の要請(例えばIOスケジューラがnoopの時を考える)を考えると, この実装も十分あると思うので確かめる必要がある. そして, もしステージングが見られなければ, このスレッショルド判定法は欠点がないと言える.

データ構造は以下,

 struct read_cache_cells {
        u32 size;
        u32 threshold;
+       sector_t last_address;
+       u32 seqcount;
+       bool over_threshold;
        struct read_cache_cell *array;
        struct hlist_head *heads;
        u32 cursor;

重要なロジックは以下,

@@ -1310,9 +1322,22 @@ static void reserve_read_cache_cell(struct wb_device *wb, struct bio *bio)
        pbd->type = PBD_WILL_CACHE;
        pbd->cell_idx = cells->cursor;

-       /*
-        * TODO mark cancelled if it's seqread.
-        */
+       if (new_cell->sector == cells->last_address + 8)
+               cells->seqcount++;
+       else {
+               cells->seqcount = 1;
+               cells->over_threshold = false;
+       }
+
+       if (cells->seqcount > cells->threshold) {
+               if (cells->over_threshold)
+                       new_cell->cancelled = true;
+               else {
+                       cells->over_threshold = true;
+                       read_cache_cancel_cells(cells, cells->seqcount);
+               }
+       }
+       cells->last_address = new_cell->sector;
 }

以上. 今回の実装で, リードキャッシングについては全実装を終了する. あとはテストをdmtsに書いていくことになる.

(追記)

さらに実験を進めた.

複数スレッドからddしたらやはりアドレスが入り混じってしまうようだ. 以下のように2スレッドでdd readすると(片方はskipでoffsetをずらしてる), ステージングが起こってしまうことが分かる. やはり, スレッショルドにはもう少し工夫が必要だ. 例えば, backgroundでステージングする時にcellをソートしてあげるというのはあるっちゃあるが, めんどくさい感じはする. まぁこれもちょっとしたエクセサイズ程度だから, やってもいいが, どの道完全にはならない意味があってうざい(例えば, 1000スレッドが同時にreadしたら, ほとんどランダムになるからもうどうしようもない). 数スレッドだったら大体OKかなという感じ.

dd if=/dev/mapper/wbdev iflag=direct of=/dev/null bs=1M &
dd if=/dev/mapper/wbdev iflag=direct of=/dev/null skip=1000 bs=1M &
wait
18:58:46          DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz     await     svctm     %util
18:58:47     dev252-0      5.00      0.00     40.00      8.00      0.15     30.00     12.00      6.00
18:58:47    dev252-16     14.00      0.00   7168.00    512.00      0.42     30.00     17.14     24.00
18:58:47    dev252-32   2438.00  19504.00      0.00      8.00    124.42     51.76      0.41    100.00
18:58:47     dev251-0   2441.00  19528.00      0.00      8.00    125.46     52.14      0.41    100.00
18:58:47     dev251-1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
18:58:47     dev251-2      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
18:58:47     dev251-3     16.00      0.00   8192.00    512.00      0.42     26.25     15.00     24.00
18:58:47     dev251-4   2442.00  19536.00      0.00      8.00    125.54     52.15      0.41    100.00