start

ZFSのヤバげな機能Special Allocation ClassがFreeBSD 12.2で対応されてた

OpenZFS 2.0リリースの陰でひっそりと、FreeBSD 12.2-RELEASEのZFS実装にSpecial Allocation Class(以下、SACと略すことがある)が追加されていた。

時系列的にはOpenZFS 2.0が2020年12月1日、FreeBSD 12.2Rが10月27日リリースなので、まったく陰ってはないんですけどね、インパクトありそうな機能の割にはリリースノートに記載がなく、zpool statusしたら「プールのアップグレードができるぜ!」と出たので調べてみたら追加されていたという。関連するコミットはこの辺→Rev.354382 Rev.354385 Rev.354941

Special Allocation Class自体はZoL 0.8.0で2019年5月24日にリリースされ、その後、illumosへのバックポートを経て、めでたくFreeBSDに取り込まれた模様。ZFS実装が新生OpenZFSベースに切り替わろうとしている中で、Legacy ZFSをきっちりメンテする姿勢には頭が下がります。

で、肝心のSpecial Allocation Classは何かというと、I/O性能に直結するデータを専用のvdevに格納して性能改善を図るもののようだ。多少正確さを欠く表現だが、階層化ストレージのZFS版といえる。

ZFSはターゲットとするデータの種類によってvdevをAllocation Classという概念で分類し、OpenZFS 2.0時点では以下の5種類のクラスが定義されている。ちなみにAllocation Classの考え方はdRAIDで導入され、その後、開発コミュニティによる汎用化を経て現在の形となったそうだ。

クラス SAC 用途 専用vdevを割り当てた時の効果
Normal × 通常のデータを扱うvdev。ミラーとかRAIDZとか。
Log × ZILのレコード。いわゆるSLOG。 同期書き込みの高速化
Dedup 重複排除テーブル(DDT)のデータ 重複排除パフォーマンスの向上とDDTのメモリ使用量の削減
Metadata プールとファイルシステムのメタデータ メタデータ操作(ファイル一覧の取得など)パフォーマンスの向上
Small Blocks レコードサイズ以下のブロック 小さなサイズの膨大なI/O性能の改善。詳細は後述

表で○を付けたクラスがSpecial Allocation Classとされている。それぞれのSACの役割は名前のごとくで、専用vdev (Special vdev)を割り当てるとそれなりに効果がありそうだ。とりわけSmall Blocksは劇的な性能改善の可能性(PDF)を秘めている。

ZFSのファイルI/Oは原則128KiB単位1)で行われる。それに満たないデータは、より小さなレコードが用いられることとなり、これらの小レコードがI/O性能にそれなりに影響するそうだ。Small Blocksは指定サイズ以下のレコードの読み書きをSpecial vdevにオフロードするような形となる。つまり、Special vdevとしてI/O性能が高いデバイス──要はSSDを割り当てると、その特性を活かして膨大な小規模I/Oを捌けるようになり、全体としてスループット向上が見込めるというワケだ。

ここで注意が必要なのは、Small Blocksの処理はファイルサイズベースではなく、レコードサイズベースで行われるということ。つまり、小さなファイルの全体がSpecial vdevに格納される訳ではない2)。ZFSの書き込みは一旦キャッシュされ、トランザクショングループ(txg)にまとめられた後にレコード単位で書き出されるため、必ずしも小さいファイル=小さなレコードとは限らない。逆に、大きなファイルでもレコードサイズ以下の端数は必ず存在するわけで、こうしたtxgを経てなおレコードサイズ未満となった分がSpecial vdev行きとなるようだ。このあたりが一般的な階層化ストレージと大きく異なる部分である。

他の階層化ストレージで見られる最頻ファイルをSSD層に配置する、といったことは(現時点では)できないが、ZFSではpL2ARC(とARC)がその役割を担っていると思われる。都度special_small_blocksの値を調整しSpecial vdevへの書き込みを制御してやれば、狙ったファイルをSSDに置くこともできなくはないが……

Small Blocksの対象となるブロックサイズは、レコードサイズ以下の2の冪を任意に指定できる。128KiB超のレコードサイズを許可するlarge_blocksフィーチャーと組み合わせると、よりパフォーマンスチューニングの幅が広がるだろう。なお、FreeBSDはレコードサイズが128KiBを超えるデータセットからの起動には対応してないので要注意。

Special Allocation Classで性能向上が見込める一方で、その仕組み上、Special vdevが死ぬと一発でプール全体のデータが飛ぶ恐れがある、というかメタデータという極めて重要なデータが飛ぶんだから、ほぼ確実に死ぬと思われる(→実際に試して死ぬことを確認)。なので今まで以上に冗長性には留意する必要がある。信頼のおけるSSDで最低でもミラーリング、可能なら電源喪失保護付きSSDで3重ミラーにしたいところ。

Special vdevの容量が一杯になった場合は、従来通り普通のvdevの方が使われるそうなので、その辺は特に気にしなくてもよい模様。

もし試す場合は、プール(普通のvdev)とSpecial vdevのashift量を一致させること。もう修正済みかもしれないが、異なるashiftでプールに追加するとSpecial vdevの取り外せなくなるバグがあるっぽい。ashift量はvdevごとに独立してて、プール作成時は気にするもののvdev追加時はついつい忘れちゃうんだよね…。


1)
データセット毎にrecordsizeプロパティで変更可能
2)
Small Blocksの閾値をレコードサイズと同値にして全データをSpecial vdevに送ることは可能だが、それなら最初からSSDでプールを組んだ方が良い

Micron 9200 MAX 1.6TBのベンチマーク

MicronのU.2接続なSSD、9200 MAX 1.6TB (MTFDHAL1T6TCU)を買ったので恒例のベンチマーク。

公称スペックは以下のとおり。

  • シーケンシャル
    • 読み込み 3500 MB/s
    • 書き込み 1900 MB/s
  • ランダム
    • 読み込み 680000 IOPS
    • 書き込み 255000 IOPS
  • TBW: 17.5PB

もちろん中古購入でS.M.A.R.T.はこんな感じ。

使用時間10047時間≒418日で、電源投入回数45回ってことは間違いなくどこかのサーバに積まれてたものだろうけど、その割に投入回数が多いような気がしなくもない。単純計算で10日に1回でしょ?読み書き量が少なめなのも謎。

1GB
MB/s
IOPS
レイテンシ
------------------------------------------------------------------------------
CrystalDiskMark 8.0.0 x64 (C) 2007-2020 hiyohiyo
                                  Crystal Dew World: https://crystalmark.info/
------------------------------------------------------------------------------
* MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s]
* KB = 1000 bytes, KiB = 1024 bytes

[Read]
  SEQ    1MiB (Q=  8, T= 1):  2638.535 MB/s [   2516.3 IOPS] <  3175.35 us>
  SEQ    1MiB (Q=  1, T= 1):  1357.518 MB/s [   1294.6 IOPS] <   771.60 us>
  RND    4KiB (Q= 32, T= 1):   339.511 MB/s [  82888.4 IOPS] <   373.57 us>
  RND    4KiB (Q=  1, T= 1):    25.252 MB/s [   6165.0 IOPS] <   161.80 us>

[Write]
  SEQ    1MiB (Q=  8, T= 1):  2011.884 MB/s [   1918.7 IOPS] <  4159.85 us>
  SEQ    1MiB (Q=  1, T= 1):  1875.930 MB/s [   1789.0 IOPS] <   558.13 us>
  RND    4KiB (Q= 32, T= 1):   293.463 MB/s [  71646.2 IOPS] <   432.32 us>
  RND    4KiB (Q=  1, T= 1):   132.838 MB/s [  32431.2 IOPS] <    30.53 us>

Profile: Default
   Test: 1 GiB (x5) [H: 0% (0/1490GiB)]
   Mode: [Admin]
   Time: Measure 5 sec / Interval 5 sec 
   Date: 2020/11/27 20:47:10
     OS: Windows 10 Professional [10.0 Build 19041] (x64)
Comment: Micron 9200 MAX 1.6TB
1GB 32GB
MB/s
IOPS
レイテンシ
------------------------------------------------------------------------------
CrystalDiskMark 8.0.0 x64 (C) 2007-2020 hiyohiyo
                                  Crystal Dew World: https://crystalmark.info/
------------------------------------------------------------------------------
* MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s]
* KB = 1000 bytes, KiB = 1024 bytes

[Read]
  SEQ    1MiB (Q=  8, T= 1):  2672.030 MB/s [   2548.2 IOPS] <  3131.79 us>
  SEQ  128KiB (Q= 32, T= 1):  2520.132 MB/s [  19227.1 IOPS] <  1661.55 us>
  RND    4KiB (Q= 32, T=16):  1474.630 MB/s [ 360017.1 IOPS] <  1416.91 us>
  RND    4KiB (Q=  1, T= 1):    23.020 MB/s [   5620.1 IOPS] <   177.46 us>

[Write]
  SEQ    1MiB (Q=  8, T= 1):  2009.463 MB/s [   1916.4 IOPS] <  4157.97 us>
  SEQ  128KiB (Q= 32, T= 1):  1999.890 MB/s [  15257.9 IOPS] <  2093.33 us>
  RND    4KiB (Q= 32, T=16):  1074.929 MB/s [ 262433.8 IOPS] <  1890.13 us>
  RND    4KiB (Q=  1, T= 1):   125.642 MB/s [  30674.3 IOPS] <    32.28 us>

Profile: Default
   Test: 1 GiB (x5) [H: 0% (0/1490GiB)]
   Mode: [Admin]
   Time: Measure 5 sec / Interval 5 sec 
   Date: 2020/11/27 20:53:28
     OS: Windows 10 Professional [10.0 Build 19041] (x64)
Comment: Micron 9200 MAX 1.6TB (NVMe SSD)
------------------------------------------------------------------------------
CrystalDiskMark 8.0.0 x64 (C) 2007-2020 hiyohiyo
                                  Crystal Dew World: https://crystalmark.info/
------------------------------------------------------------------------------
* MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s]
* KB = 1000 bytes, KiB = 1024 bytes

[Read]
  SEQ    1MiB (Q=  8, T= 1):  3559.011 MB/s [   3394.1 IOPS] <  2354.13 us>
  SEQ  128KiB (Q= 32, T= 1):  3562.092 MB/s [  27176.6 IOPS] <  1174.93 us>
  RND    4KiB (Q= 32, T=16):  1965.045 MB/s [ 479747.3 IOPS] <  1032.14 us>
  RND    4KiB (Q=  1, T= 1):    35.869 MB/s [   8757.1 IOPS] <   113.71 us>

[Write]
  SEQ    1MiB (Q=  8, T= 1):  1989.156 MB/s [   1897.0 IOPS] <  4205.01 us>
  SEQ  128KiB (Q= 32, T= 1):  2013.703 MB/s [  15363.3 IOPS] <  2078.83 us>
  RND    4KiB (Q= 32, T=16):  1462.729 MB/s [ 357111.6 IOPS] <  1387.32 us>
  RND    4KiB (Q=  1, T= 1):   130.202 MB/s [  31787.6 IOPS] <    31.17 us>

Profile: Default
   Test: 32 GiB (x5) [H: 0% (0/1490GiB)]
   Mode: [Admin]
   Time: Measure 5 sec / Interval 5 sec 
   Date: 2020/11/27 21:05:36
     OS: Windows 10 Professional [10.0 Build 19041] (x64)
Comment: Micron 9200 MAX 1.6TB (NVMe SSD)
1GB 10GB
MB/s
IOPS

ベンチしてて気になったのは、S.M.A.R.T.が報告する温度が高めということ。

最初、バラック状態でやってたら70℃近くまで上がったため、急遽ファンで直接風をあてた。本当に70℃まで上がってたら熱くて触れないハズだが、実際は多少熱いくらいの温度感だった。15mm厚のSSDかつゴツい金属製筐体なので放熱性は良さそうなんですがね…。

ドライブ内部の一番ホットな部分の温度を示してるのか、センサー故障で高めの値なのか真相は不明。

それと、PCIeのリンク状態が割とシビアな気がする。2台のマシンで、PCIeスロットにマウントするタイプの変換カード、PCIe→SFF-8643→SFF-8639ケーブルのそれぞれで接続したが、どちらとも最初はPCIe 2.0でのリンクアップとなってしまった。コネクタ抜き差しでPCIe 3.0で繋がったものの、少々気がかりではある。

OpenZFS 2.0リリース!!

本日、ついにOpenZFS 2.0がリリースされた!!

リリースノート:Release OpenZFS 2.0.0 · openzfs/zfs · GitHub

ZFS環境的には、なんといってもLinuxとFreeBSD向けの実装が統合され、1つのソースツリーからビルドされるようになったのが大きい。実態としては、以前から書いてきたとおり、ZFS on LinuxプロジェクトがOpenZFSプロジェクトとなり、FreeBSD向けの修正が行われたという感じで、“統合”って感じではないんだけど、いずれにせよZFSを取り巻く環境は今後ますます発展していくことだろう。

機能面では、永続的L2ARCと圧縮アルゴリズムとしてZStandardが追加されたのが大きいかな。

これを書いている時点で、PortsのOpenZFSの方はまだ更新されてないが、遅かれ早かれ2.0になると思われる。FreeBSDのベースシステムのZFS実装が置き換わる具体的な時期は不明だが、当初の計画では13.0-RELEASEで置き換わることになってたはず。こちらも無事に進んでくれることを祈りたい。

FreeBSD 12.1のvirtioドライバはバグってるっぽい?

FreeBSD 12.1-RELEASEのvirtioドライバは何かしら不具合があるようだ。仮想環境のゲストとして動かした際に、virtio経由のデバイスが認識されなかったり正しく動かなかったりする模様。もしかすると、12.0-RELEASEや11.3でも同様かも。

このところProxmox VEにお熱で、自宅のFreeBSDサーバをP2Vすべく調査や実験を行っている。P2Vと言ってもPCIパススルーやRaw Device Mappingなどを使い、本来の仮想化とは少々毛色が違うのだが、この構成にしとけばいつでもV2P出来るというメリットがある。

そんなわけで、起動ディスクのNVMe SSDをPCIパススルーし、VMを起動して無事FreeBSDの起動シーケンスが流れてktkrと思ってたら、忌まわしき「Mounting from zfs:zroot/ROOT failed with error 5.」で止まってしまった。

ZFSでこのエラーになってしまったら、ここから復旧できる見込みはまずない。

仕方ないのでProxmoxやVMの設定、KVMのパススルーまわりのあれこれの見直し、FreeBSD側の/boot/loader.confのチェックにzpool.cacheの再生成など、知る限りのあらゆることを試しても症状は変わらず。

起動メッセージをよーく確認すると「ptnetmap-memdev0: cannot map I/O space」「device_attach: ptnetmap-memdev0 attach returned 6」がチラホラ出ていた。

それらしい単語でググるとVirtio fails as QEMU-KVM guest with Q35 chipset on Ubuntu 18.04.2 LTSがヒットした。試したVMは確かにQ35で作ってるし、自分と同じくルートプールが見つからなくて起動できない報告もあるし、このバグを踏んだか?

スレを読んでも修正されたんだかされてないんだか分らなかったが、ふと、先行実験でパススルーしたNVMe SSDにインストールした12.2-RELEASEは問題なく起動してたのを思い出した。それならばってことで、いったん通常環境でFreeBSDを起動し、12.2-RELEASEに更新。その後、改めてVMの方で試したら何事もなかったかのように動いた。マジかよ…(ヽ'ω`)

Proxmox VE 6.2とX10DRiとR7 430でGPUパススルーできた

念願のGPUパススルーができたので、記録として書き止め。環境は以下のとおり。

  • Proxmox VE 6.2-4
  • X10DRi
  • Xeon E5-2648Lv3 (VMに4コア割り当て)
  • Radeon R7 430
  • Windows 10 (20H2/x64)

ググれば出てくる方法で、何の苦労もなくできた。記念にDQXベンチVer.1.51の結果をペタり。

最高品質、1920×1080の設定でスコア7256のとても快適の評価となった。Twitterから同スコアを拾ってくると4700、7800、8000、8600、9400って感じでバラついてて何とも言えない所ではあるが、GPUパススルーのオーバーヘッドはそれほど大きくはなさそう。

ついでにリモートデスクトップ経由でベンチした結果はこちら。

これでメインマシンをサーバに収容する計画が一歩前進だなー。実現した場合、Ryzen 3.0GHzおじさんからHaswell-EP 1.8GHzおじさんへと大幅退化することになるわけだが…。H11SSL-iとEPYCほすぃ……。

  • start.txt
  • 最終更新: 2022-07-27 15:26
  • by Decomo