えいのうにっき

主に Web 系技術ネタ。背景画像 is powered by grass-graph.shitemil.works

読書メモ・詳解システムパフォーマンス 第8章/ファイルシステム

「詳解システムパフォーマンス」の読書メモシリーズ・第7弾。

詳解 システム・パフォーマンス

詳解 システム・パフォーマンス

感想

読書メモ

8.1 用語

8.2 モデル

8.2.1 ファイルシステムインターフェイス

基本モデルとしては、アプリケーションとストレージデバイスの間にファイルシステムは位置し、I/Oの橋渡しをしている。

8.2.2 ファイルシステムキャッシュ

  • データの読み出しはキャッシュかディスクからデータを得る
  • キャッシュミスを起こしたディスクデータはキャッシュに格納される(キャッシュウォームアップ)
  • 書き込みデータをあとで書き込むバッファリングもファイルシステムキャッシュの役割。

8.2.3 2次キャッシュ

RAMが用いられる1次キャッシュに対し、2次キャッシュはどのようなメモリタイプでも良い。

8.3 コンセプト

8.3.1 ファイルシステムレイテンシ

8.3.2 キャッシング

  • ファイルシステムはブート後、パフォーマンス向上のためにメインメモリをキャッシュとして使い、時間とともにキャッシュは成長(肥大)する
    • OSが使えるフリーメモリも減っていくが、これは正常な動作。
    • ファイルシステムキャッシュは、カーネルから優先的に開放されるようになっている
  • ファイルシステムキャッシュには以下のようなキャッシュタイプがある。
    • ページキャッシュ
    • ファイルシステム プライマリキャッシュ
    • ファイルシステム セカンダリキャッシュ
    • ディレクトリキャッシュ
      • ファイルパス名の情報を格納し、メモリ上にキャッシングしているもの。パス検索の高速化が目的
      • dentryという構造体に格納されている
    • iノードキャッシュ
    • バイスキャッシュ
      • バイスに備わっているキャッシュ?
    • ブロックデバイスキャッシュ
      • いわゆるバッファキャッシュ

8.3.3 ランダムI/OとシーケンシャルI/O

  • シーケンシャルI/O
    • 前のI/Oの末尾から次のI/Oが始まる
  • ランダムI/O
    • 前後のI/Oに特別な関係はなく、オフセットは不規則に変化する

8.3.4 プリフェッチ

  • ファイルシステムが論理I/Oアクセスパターンを計測し、シーケンシャルなワークロードを区別してプリフェッチや先読みを使ってパフォーマンスを上げようとするための仕組み
  • アプリケーションが要求する前にディスク読み出しを予測して発行する
    • 読み出されたデータはファイルシステムキャッシュにセットされ、予測通りの読み出しをアプリケーションが実行したときにはキャッシュヒットが起きる
  • プリフェッチがうまく機能しなかった場合、アプリケーションが必要としない不要なI/Oが発行され、キャッシュも汚れ、ディスク、I/Oトランスポートリソースが無駄に使われる

8.3.5 先読み

  • 伝統的に、プリフェッチは「先読み」とも呼ばれてきた

8.3.6 キャッシュの書き戻し

  • 書き込みのパフォーマンスをあげるためのファイルシステムの仕組み
  • メインメモリへの転送が終わったら書き込みを完了扱いにするもの
  • 転送されたデータは、非同期的にディスクに書き戻しされる(フラッシング
  • メリットばかりではなく、sd 信頼性とトレードオフになる。
    • DRAMベースのメインメモリは揮発性なので、電源で障害が起きると、「アプリケーションは書き込みを完了したと判断していても、ダーティデータは失われる」可能性がある
    • ダーティデータが不完全にディスクに書き込まれる場合もあり、その場合にはディスク上の状態はこわれてしまう
  • ファイルシステムは、デフォルトではキャッシュの書き戻しをサポートしているものの、この動作をバイパスして永続ストレージデバイスに直接書き込む同期書き込みオプションもサポートされている

8.3.7 同期書き込み

  • データベースのログライターなど、非同期書き込みによるデータ破壊のリスクが許容できない一部のアプリケーションで利用されている
  • 同期書き込みの形態は以下の2つ
    • 個別の同期書き込み
    • 一連の書き込み要求グループの同期コミット
      • 個別のI/Oを同期的に行なうのではなく、コード内のあるチェックポイントでそれまでの非同期書き込みを同期的にコミットすることができるもの

8.3.8 Raw I/O と Direct I/O

8.3.9 ノンブロッキングI/O

  • ディスクデバイスI/Oなどにより待機が必要な場合、アプリケーションスレッドはブロックしてCPUを手放し、他のスレッドがCPUを利用できるようにする
  • マルチスレッドアプリケーションならば特に問題になることは少ないが、スレッド作成のパフォーマンス、リソース麺でのオーバーヘッドを避けるために、ブロックされないことが望ましい場合もある
  • ノンブロッキングI/Oでは、ブロックせずにエラーが返されるようになる

8.3.10 メモリマップトファイル

8.3.11 メタデータ

8.3.12 論理I/Oと物理I/O

  • アプリケーションがファイルシステムに要求するI/O ≠ ディスクI/O(物理I/O)
    • アプリケーションからのI/O要求とは無関係なもの、間接的なもの、アプリケーションからのI/O要求よりも膨らんでいるもの・小さくなっているもの、がある
  • 無関係なもの
    • ほかのテナントによるディスクI/O
    • カーネルの他のタスクによるディスクI/O
  • 間接的なもの
  • 縮小されるもの
    • ファイルシステムのキャッシングが効いている場合
    • ファイルシステムへの書き込みの相殺(バッファリングされたがディスクにフラッシングされる前に複数回書き換えられたような場合。
    • 圧縮:論理I/Oのデータ量を圧縮して物理I/Oをおこなう
    • 結合:ディスクに書き込みを行う前にシーケンシャルI/Oをまとめる
    • インメモリファイルシステム:内容がディスクに書き込まれない
  • 膨らむもの

8.3.13 オペレーションは平等ではない

  • 8.3.12 のように、オペレーションの頻度だけでワークロードを比較しても意味がない。

8.3.14 特殊なファイルシステム

  • /dev や /proc 、/tmpなど。これらは永続的にデータを格納することが目的ではない。

8.3.14 アクセスタイムスタンプ

  • これがあるため、ファイルを読み出すたびにファイルメタデータの更新がおこなわれ、ディスクI/Oを消費するワークロードが発生してしまう

8.3.16 容量

  • ファイルシステムがいっぱいになってくると、パフォーマンスもさまざまな理由により低下する
    • 新しいデータを書き込むとき、ディスク上のフリーブロックを見つけ出すための計算や実際に必要となるディスクI/Oのために、余計に時間が掛かってしまう場合がある
    • ディスク上のフリー領域は小さくなり、離れた位置に散財するようになって、小規模なI/OやランダムなI/Oのためにパフォーマンスは下がりがちになる

8.4 アーキテクチャ

8.4.1 ファイルシステムI/Oスタック

8.4.2 VFS

8.4.3 ファイルシステムキャッシュ

  • Unix はもともとバッファキャッシュしか持っていなかった
  • バッファキャッシュ
    • Linux 2.4 以降、バッファキャッシュはページキャッシュ内に格納されるようになった
      • buffer と cache で見られるサイズは別々になっている?
    • バッファキャッシュの機能はまだ残っており、ブロックデバイスI/Oのパフォーマンスを向上させている
    • サイズは動的に変化する
  • ページキャッシュ
    • ファイルシステムページを含む仮想メモリページをキャッシングし、ファイルとディレクトリのI/Oのパフォーマンスを向上させている
    • 書き換えられたメモリページやファイルシステムが使っているページは、カーネルスレッドによってディスクにフラッシュされる
    • システムメモリが足りなくなると、ページアウトデーモンという別のカーネルスレッドが、ディスクに書き込むべきダーティページを見つけてスケジューリング、そのページを開放して再利用できるようにする
  • dentry cache(Dcache)
    • ディレクトリエントリから VFS iノードへのマッピングを記憶する
    • パス名ルックアップのパフォーマンスが上がる
    • ネガティブキャッシング:存在しないエントリのルックアップを記憶する
      • 失敗したルックアップのパフォーマンスを向上させる
  • iノードキャッシュ
    • VFS iノードを格納する
    • ファイルシステムワークロードのために頻繁にアクセスされる
    • 高速でスケーラブルなルックアップのために、ハッシュテーブルに格納される
      • ただし殆どのルックアップは dentry cache を介しておこなわれる。
    • iノードキャッシュは、少なくとも Dcache がマッピングするすべてのiノードを格納し、動的に成長する
    • システムメモリが足りなくなると、iノードキャッシュは dentry と対応関係を持たない iノードを破棄する

8.4.4 ファイルシステムの機能

  • ブロックとエクステント
    • ブロックベースのファイルシステムは、固定サイズのブロックにデータを格納する
      • ブロックは、メタデータブロックに格納されるポインタによって参照される
      • 大きなファイルの場合、多数のブロックポインタとメタデータブロックが必要になる。ブロックの配置もバラバラになりやすく、ランダムI/Oを引き起こしやすくなる
    • エクステントベースのファイルシステムは、ファイル(エクステント)のために連続的なスペースをプレアロケートし、必要に応じてそれを成長させる
      • スペースのオーバーヘッドのためコストはかかるが、ストリーミングのパフォーマンスが上がり、ファイルデータが局所化される。ひいてはランダムI.Oのパフォーマンスを向上させられる
  • ジャーナリング
  • コピーオンライト
    • 「新しい位置にブロックを書き込む」「参照を新ブロックに更新する」「古いブロックをフリーリストに追加する」といった手順に従って更新をおこなうのが「コピーオンライトファイルシステム
  • スクラビング
    • 全てのデータブロックを非同期に読み出し、チェックサムを確認して、出来る限り早くエラーを検出する、ということのためのファイルシステムの機能
    • スクラビング読み出しI/Oはパフォーマンスにマイナスの影響を及ぼすこともあるので、優先度を挙げて実行すべき。

8.4.5 ファイルシステムのタイプ

  • FFS
    • オリジナルのUnixファイルシステムの問題点に対処するために設計されたもの
    • 多くのファイルシステムがFFSを基礎としている
    • オリジナルのUnixファイルシステムには、以下のような問題点があった
      • ディスク上のレイアウト
        • iノードテーブル(512バイトのブロック)とストレージブロックはディスクのパーティションをふたつの範囲に分割しており、両者の間でシークするときにパフォーマンス上の問題を引き起こしていた
        • 512バイトという小さな固定サイズのブロックを用いていたのも、スループットを下げ、大きなファイルを格納するために必要なメタデータの量を増やしてしまう問題があった
        • ファイルの作成・削除をおこなううちにフリーリストがフラグメンテーションを起こしてしまう、すべてのブロックアクセスに先立ってシークが必要になってしまう
    • FFSはパーティションを無数のシリンダーグループ(シリンダーグループヘッダ/iノード配列/データブロック で構成される)に分割することでパフォーマンスを引き上げた
      • ファイルのiノードとデータは、可能なら同じシリンダーグループに格納される・他の関連データも、ディレクトリとそのエントリのiノードを含め、近隣に配置されるようになった
      • ブロックサイズも、最小で4kbに拡張された
    • ブロックのインターリービング
      • シーケンシャルなファイルブロックがディスク上でひとつ以上のブロックを間に挟んだ形で並ぶように配置すること
      • カーネルとプロセッサが、次のシーケンシャルなファイル読み出し要求を発行する時間を稼ぐため
      • これがなければ、読み出し要求を発行する準備が整う前に次のブロックがディスクヘッドに渡されるため、ほぼ1回転分の待ちが必要になり、ひいてはそれがレイテンシとなってしまう
  • UFS
    • UFSのパフォーマンス関連機能
    • I/Oクラスタリング
      • クラスタがフルになるまで書き込みを先延ばしにし、ディスク上のデータブロックをグループ化し、データブロックをシーケンシャルに配置できるようにする仕組み
      • シーケンシャルな読み出しワークロードが検出されると、UFSはクラスタを読み出してプリフェッチを実行する
    • ロギング
      • メタデータのみを対象
      • ログのリプレイによりfsck(File System ChecK)の実行を省けるようになるため、システムクラッシュ後のブートのパフォーマンスが上がる
      • メタデータの書き込みをまとめることによって書き込みワークロードの一部のパフォーマンスも向上する
    • Direct I/O
      • ページキャッシュをバイパスし、キャッシュの重複を避ける
  • ext3
    • Linux拡張ファイルシステムの第3バージョン。
    • ジャーナリング
      • オーダードモード(メタデータのみ)とジャーナルモード(メタデータとデータの両方)がある
      • システムクラッシュが起きたときに、変更をアトミックに再現するための仕組み。
      • fsck(File System ChecK)の実行を省けるようになるため、システムクラッシュ後のブートのパフォーマンスが上がる
      • メタデータの書き込みをまとめることによって書き込みワークロードの一部のパフォーマンスも向上する
    • ジャーナルデバイス
      • ジャーナリングに外部のジャーナルデバイスを使用できる
      • ジャーナルのワークロードがその他のワークロードと衝突するのを防ぐことができる
    • Orlovアロケータ
      • トップレベディレクトリをシリンダーグループ全体に分散させることで、サブディレクトリと内容が近くに並びやすくなり、ランダムI/Oが減る
    • ディレクトリインデックス
  • ext4
    • さまざまな機能の追加やパフォーマンスの改善によってext3を拡張したもの
    • エクステント
      • 連続的な配置を改善し、ランダムI/Oを減らし、シーケンシャルI/OのI/Oサイズを増やす
    • プレアロケーション
      • 連続的になりそうなスペースを前もってアロケートする
    • 遅延アロケーション
      • ブロックがディスクにフラッシュされるまで、ブロックのアロケーションを先延ばしにす、マルチブロックアロケータを使ってグループに書き込めるようにすることで、フラグメンテーションを防ぐ
    • 高速fsck
      • アロケートされていないブロックとiノードエントリにマークを付け、fsckの処理時間を短縮する
  • ZFS
    • ファイルシステムとボリュームマネージャを結合し、エンタープライズ向け機能を数多くサポートしている
    • ファイルサーバ向けのファイルシステムとして。
    • プール化されたストレージ
    • COW
      • データをグループにまとめて逐次的に書き込む
    • ロギング
      • 全体として成功するか失敗するかになる変更のトランザクショングループをフラッシュすることで、ディスク上のフォーマットは常に一定に保たれる
      • バッチで書き込みをおこなうので、非同期書き込みのスループットが上がる
    • ARC
      • Adaptive Replacement Cache・適応型置換キャッシュ
      • MRUとMFUという複数のキャッシュアルゴリズムを同時に使って、それぞれのキャッシュアルゴリズムのパフォーマンスに基いてメインメモリをバランスよく使い、キャッシュのヒット率を上げる
    • 可変長ブロックサイズ
      • 構成可能な最大ブロックサイズを持ちながら、ワークロードに合わせてブロックサイズを選ぶことができる
      • 小さなファイルには小さなサイズが用いられる
    • 動的ストライピング
      • すべてのストレージデバイスにまたがってストライピング(複数台のディスクに分散して書き込み)する
    • インテリジェントプリフェッチ
      • メタデータ、ファイルコンテンツ、vdev(仮想デバイス)それぞれごとに異なるタイプのプリフェッチを使い分ける
    • マルチプリフェッチストリーム
      • ひとつのファイルに複数のストリーミングリーダーを設け、ファイルシステムがリーダー間をシークするとランダムI/Oワークロードが作られるが、ZFSでは個々のプリフェッチストリームを管理し、新しいストリームを追加できるようにしている。これにより、I/O要求を効率的に発行する
    • スナップショット
      • COWアーキテクチャのおかげで、ほとんど瞬間的にスナップショットを作成することができる
    • ZIOパイプライン
      • ZFS I/O Pipline http://solaristic-days.blogspot.jp/2012/09/zfs.html
      • ZIO パイプラインは、ディスクに送受信されるすべてのデータが通過する
        • DVA (Device Virtual Address) を vdev 上の論理的位置に変換するだけでなく、必要に応じてデータのチェックサムの計算や、データの圧縮を行う
      • ZIO は複数ステージのパイプラインとして実装され、各 I/O に対して、どのステージを実行するかを制御するビットマスクを持っている
      • バイスI/Oはステージのパイプラインによって処理される
      • 各ステージはパフォーマンスを上げるためにスレッドプールによって処理される
    • 圧縮
      • 圧縮は通常、CPUにオーバーヘッドをかけてパフォーマンスを下げるが、lzjbオプションは軽く、CPUにある程度コストをかけた分、I/Oの負荷を下げることで、わずかながらストレージのパフォーマンスを上げる
    • SLOG
      • Separate intent LOG
      • 同期的な書き込みが別のデバイスに書き込まれるようにして、プールディスクのワークロードと競合を起こさないようにする
      • SLOGに書き込まれた内容は、システムがエラーを起こしたときに、リプレイのために読み出されるだけ。
    • L2ARC
      • メインメモリのあとの第2レベルのキャッシュで、欄抱く読み出しワークロードをSSDにキャッシングすることを目的としたもの
      • 書き込みワークロードのバッファリングはおこなわず、すえにストレージプールディスクにあるクリーンなデータだけを格納する
      • システムがキャッシングできるリーチを広げ、ワークロードがメインメモリキャッシングを超えて成長したときのパフォーマンスの急激な低下を防ぐ
    • vdevキャッシュ
      • 仮想デバイスごとにLRUと先読みをサポートする別個のvdevキャッシュを使っている
    • データのデデュプリケーション
      • 同じデータの複数のコピーを記録することを避ける、ファイルシステムレベルの機能
      • メリットはデバイスI/Oの削減。デメリットは、ハッシュテーブルがメインメモリに収まりきらなくなると、デバイスI/Oが急激に増えるおそれがあること。
    • Don’t mind the gap
      • 小さな不要部分があっても、適切であれば大きな読み出しを発行する
    • キャッシュフラッシュ
      • ZFSでデフォルトで有効になっている機能。
      • 電源が落ちたときに書き込みが確実に完了するように、ストレージデバイスにキャッシュフラッシュコマンドを発行するようになっている
      • ほかのファイルシステムとくらべてパフォーマンスが下がる原因になる
  • Btrfs
    • B-tree file system
    • コピーオンライトでB木を基礎としている
    • まだ不安定だと考えられている
    • プール化されたストレージ
    • COW
      • データをグループにまとめて逐次的に書き込む
    • オンライン平準化
      • ワークロードを平準化するために、ストレージデバイス間でオブジェクトを移動できる
    • エクステント
      • 連続的な配置を改善し、ランダムI/Oを減らし、シーケンシャルI/OのI/Oサイズを増やす
    • スナップショット
      • COWアーキテクチャのおかげで、ほとんど瞬間的にスナップショットを作成することができる
    • 圧縮
      • zlibとLZOをサポートする
    • ジャーナリング
      • 同期的なCOWワークロードをジャーナリングするために、サブボリュームごとにログツリーをつくることができる

8.4.6 ボリュームとプール

  • ボリュームとプールによって、複数のディスクの上にファイルシステムを作り、異なるRAIDを使うように構成できるようになる
  • ボリューム
    • 複数のディスクをひとつの仮想ディスクのように見せるもの。その上にファイルシステムが構築される
    • スライスやパーティションではなく、ディスク全体の上にボリュームを作ると、ボリュームによってワークロードが隔離され、競合によってパフォーマンスが損なわれる問題を減らすことができる
    • Linuxのボリューム管理ソフトウェアとしては、LVMがある
  • プール化ストレージ
    • ストレージプールに複数のディスクを組み込み、そこから複数のファイルシステムを作れるというもの
    • 背後のデバイスにかかわらず拡大/縮小できるため、ボリュームよりも柔軟性が高い
    • すべのファイルシステムのためにすべてのディスクデバイスを使うことができ、パフォーマンスが向上する
    • ワークロードは隔離されない
  • ソフトウェアボリュームマネージャとプール化ストレージのどちらを使うかに関して、パフォーマンス上考慮すべきこととしては、以下のようなものがある
    • ストライプの幅:ワークロードに合わせる
    • 可観測性:仮想デバイスの使用率は紛らわしいので、物理デバイスを別々にチェックする
    • CPUのオーバーヘッド:特にRAIDパリティ計算。
    • ミラー再同期:RAIDグループに空のディスクを追加したとき、その空ディスクにグループに参加するために必要なデータを書き込むこと。リビルド・再構築、とも。同期にはI/Oリソースを消費し、数時間から数日要するため、パフォーマンスに大きな影響を及ぼす

8.5 メソドロジ

8.5.1 ディスクの分析

8.5.2 レイテンシの分析

  • まずファイルシステムオペレーションのレイテンシを計測するところからはじめる
    • I/Oだけでなく、全てのオブジェクトオペレーションを含む必要がある
    • オペレーションのレイテンシ=オペレーション完了時刻 - オペレーション要求時刻
  • ファイルシステムレイテンシを分析するためのターゲット(レイヤ)
  • レイテンシの表示形式
    • 間隔あたりの平均値(ex.1秒あたりの平均読み出しレイテンシ)
      • キャッシュヒット率が高いファイルシステムでは、この値はキャッシュヒットレイテンシに引きずられる。
    • 完全な分布(ex.ヒストグラムやヒートマップ)
      • 間隔あたりの平均値では、外れ値を見極めることが大切だが、わかりにくいため、分布を用いる。
      • 高いレイテンシが見つかったら、さらにドリル分析をすることで原因を特定していく
    • オペレーションごとのレイテンシ・すべてのオペレーションのリスト
  • トランザクションのコスト

8.5.3 ワークロードの特性の把握

  • ファイルシステムのワークロードを特徴づける基本属性には以下のようなものがある。これらは毎秒変化する可能性がある。特性をうまく掴むためには、平均値だけでなく最大値もチェックするようにする。
    • オペレーションの速さとタイプ
    • ファイルI/Oのスループット
    • ファイルI/Oのサイズ
    • 読み書きの比率
    • 同期書き込みの比率
    • ファイルオフセットへのランダムなアクセスとシーケンシャルなアクセス
  • 高度なワークロードの抽出/チェックリスト
    • ファイルシステムキャッシュのヒット率はどのようになっているか。ミス率はどれくらいか。
    • ファイルシステムキャッシュの容量と現在の使用状況はどうなっているか
    • ほかにどのようなキャッシュ(ディレクトリ/iノード/バッファ)があるか。それらの統計はどうなっているか。
    • どのアプリケーション・どのユーザーがファイルシステムを使っているか。
    • どのファイル・ディレクトリがアクセスされているか。作成・削除されているファイルはどれか。
    • エラーは起きているか。
    • ファイルシステムI/Oはなぜ発行されているのか。
      • ユーザーレベルコールパスはどうなっているか。
    • ファイルシステムI/Oのうちどれくらいの割合が同期的なものか。
    • I/Oの到着時間の分布はどうなっているか。
  • パフォーマンスの特性の把握
    • ファイルシステムオペレーションの平均的レイテンシはどれくらいか。
    • レイテンシの高い外れ値はあるか。
    • オペレーションのレイテンシの完全な分布はどうなっているか。
    • ファイルシステムやディスクI/Oに対するシステムリソースはあるか・アクティブになっているか。

8.5.4 パフォーマンスモニタリング

  • 「オペレーションの頻度」「オペレーションのレイテンシ」が、ファイルシステムパフォーマンスの主要な指標。
  • これらは、オペレーションタイプ(読み出し/書き込み/詳細情報取得/オープン/クローズ/その他)ごとに記録することも良い
  • ファイルシステムベースのリソースコントロールがあるシステム(ex.ZFSのI/Oクォータ)では、それが使われているか・いつ使われているかを示す統計値も含める。

8.5.5 イベントトレーシング

  • 観察的な分析では最後の手段。あらゆるファイルシステムオペレーションの詳細を把握する
    • 詳細情報のキャプチャ、保存のためにパフォーマンスにオーバーヘッドを加えることになるので注意する
  • 以下のような詳細情報がログファイルに書き込まれる
    • ファイルシステムのタイプ
    • ファイルシステムのマウントポイント
    • オペレーションのタイプ
    • オペレーションサイズ(バイト数)
    • オペレーションの開始(オペレーションが発行された)タイムスタンプ
    • オペレーションの完了タイムスタンプ
    • オペレーションの完了ステータス
    • プロセスID - アプリケーション名
  • 出力のフィルタリング機能もある・特定の閾値よりも遅いオペレーションだけをログに書き込むことができるので、適切にフィルタリングを実施する

8.5.6 静的パフォーマンスチューニング

8.5.7 キャッシュチューニング

  • 以下のような項目をチェックし、キャッシュされるワークロードをチューニングして、ワークロードに合わせてキャッシュをチューニングする。
    • どのキャッシュがあるか
    • それらが動作しているか
    • うまく機能しているか
    • サイズはどうなっているか

8.5.8 ワークロードの分離

  • ワークロードのなかには、専用のファイルシステムとディスクデバイスを使うように構成したほうがパフォーマンスが上がるものもある
    • 回転ディスクでは、ふたつの異なるワークロードの間でシークしながらランダムI/Oをおこなうのは特にパフォーマンスが低い(スピンドルの分離)
    • データベースでは、ログ・ファイルとデータベースファイルとで別々のファイルシステム・ディスクを使うと効果的、など。

8.5.9 メモリベースのファイルシステム

  • メモリベースのファイルシステムを使うことも、構成からパフォーマンスを向上させるアプローチのひとつ。
  • 多くのアプリケーションは独自の固有キャッシュをプロセスメモリ内に持っていて、それらの方がファイル、システムコールインターフェイスを経由するよりも効率よくアクセスできるので、メモリベースのファイルシステムが使われるのは、そういった機能がないときだけ、と考える。
  • /tmp は、一般にメモリベースで構成される。

8.5.10 マイクロベンチマーキング

  • ファイルシステムとディスクのベンチマークツールを使うことで、特定のワークロードに対するさまざまなファイルシステムタイプのパフォーマンスやファイルシステム内の設定がパフォーマンスに与える影響をテストすることができる。
  • テストされる要素
    • オペレーションタイプ
    • I/Oのサイズ
    • ファイルオフセットのパターン(ランダム/シーケンシャル)
    • ランダムアクセスのパターン(一様分布/パレート分布)
    • 書き込みタイプ(非同期/同期)
    • ワーキングセットサイズ
      • ファイルシステムキャッシュにどれくらいうまく収まっているか。
      • これが小さいと、全ての読み出し要求がメインメモリのファイルシステムキャッシュから結果を得ることができる
    • 並行処理
      • 実際に実行されているI/Oの数、またはI/Oを実行しているスレッドの数
    • メモリマッピング
    • キャッシュの状態(コールド or ウォーム)
    • ファイルシステムのチューニング可能パラメータ
      • 圧縮、デデュプリケーションなど
  • 一部のディスクベンチマークツールは、キャッシングやバッファリングを防ぐためにDirect I/Oによってファイルシステムを経由して動作する。これによりファイルシステムのワーストケース(キャッシュヒット率0%)のパフォーマンスのテストをすることができる

8.6 分析

8.6.1 vfsstat

  • VFSレベルで iostat 的なことをするツール。ワークロードと得られたパフォーマンスの特性を示す情報を表示する
  • 平均レイテンシを含む時間間隔あたりのファイルシステムオペレーション(論理I/O)の概要を表示する
  • iostat (非同期タイプを含むディスクI/O(物理I/O)を表示する)よりも、アプリケーションのパフォーマンス情報に近い。

8.6.2 fsstat

  • Solaris向けツール
  • ワークロードの特性の把握に使える
  • レイテンシ統計は含まれていない

8.6.3 strace(Linux), truss(Solaris

8.6.4 DTrace

8.6.5 SystemTap

8.6.6 LatencyTOP

  • レイテンシの原因を明らかにするツール
  • システム全体での集計とプロセスごとの情報の両方を表示する

8.6.7 free

$ free
              total        used        free      shared  buff/cache   available
Mem:        1015472      808872       78528        1880      128072       67824
Swap:       2097148      233620     1863528
  • cache はページキャッシュのサイズ。

8.6.8 top

KiB Mem :  1015472 total,    67468 free,   808384 used,   139620 buff/cache

8.6.9 vmstat

$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 233456  67596      0 139684   16   10   123    14    1    2  1  0 98  0  0
  • buff はバッファキャッシュのサイズ、 cache はページキャッシュのサイズ。

8.6.10 sar

  • ファイルシステムのさまざまな統計情報を表示し、履歴を記録するように構成することができる
$ sar -v 1
Linux 3.10.0-327.10.1.el7.x86_64 (hoge-host)    2017年08月14日   _x86_64_    (1 CPU)

13時36分24秒 dentunusd   file-nr  inode-nr    pty-nr
13時36分25秒      2503      2624     13616         1
13時36分26秒      2503      2624     13616         1
13時36分27秒      2503      2624     13616         1
  • -v オプションにより、以下のような情報が得られる。
    • dentunusd
      • 未使用のディレクトリエントリキャッシュの数(利用可能エントリ数)
    • file-nr
    • inode-nr
      • 使われているiノードの数
  • -r オプションにより、バッファキャッシュとページキャッシュのサイズを kb 単位で示す kbbuffers kbcached を表示させることもできる。
$ sar -r 1
Linux 3.10.0-327.10.1.el7.x86_64 (hoge-host)    2017年08月14日   _x86_64_    (1 CPU)

13時38分28秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
13時38分29秒     66308    949164     93.47         0     79628   1387840     44.59    435024    409956        64
13時38分30秒     66308    949164     93.47         0     79628   1387840     44.59    435032    409956        64
13時38分31秒     66308    949164     93.47         0     79628   1387840     44.59    435036    409956        64

8.6.11 slabtop

  • カーネルスラブキャッシュについての情報を表示する
$ sudo slabtop -o
 Active / Total Objects (% used)    : 557041 / 604259 (92.2%)
 Active / Total Slabs (% used)      : 8112 / 8112 (100.0%)
 Active / Total Caches (% used)     : 65 / 95 (68.4%)
 Active / Total Size (% used)       : 49217.77K / 60528.50K (81.3%)
 Minimum / Average / Maximum Object : 0.01K / 0.10K / 8.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
123264 122105  99%    0.03K    963      128      3852K kmalloc-32             
121720 121720 100%    0.02K    716      170      2864K fsnotify_event_holder  
 81408  81408 100%    0.01K    159      512       636K kmalloc-8              

8.6.12 mdb ::kmastat

8.6.13 fcachestat

  • Perl の Sun::Solaris::Kstat ライブラリを使う Solaris ベースシステム用のオープンソースツール
  • UFS上のキャッシュアクティビティ分析に適した集計を表示する

8.6.14 /proc/meminfo

  • メモリ分析の集計情報を格納する
    • free(1) などのツールがこれを読み出している
$ cat /proc/meminfo
MemTotal:        1015472 kB
MemFree:           65052 kB
MemAvailable:      60592 kB
Buffers:               0 kB
Cached:            79624 kB
SwapCached:        31660 kB
Active:           436948 kB
Inactive:         409144 kB
Active(anon):     382516 kB
Inactive(anon):   385964 kB
Active(file):      54432 kB
Inactive(file):    23180 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       2097148 kB
SwapFree:        1864112 kB
Dirty:                20 kB
Writeback:             0 kB
AnonPages:        754956 kB
Mapped:            22372 kB
Shmem:              2012 kB
Slab:              61036 kB
SReclaimable:      26088 kB
SUnreclaim:        34948 kB
KernelStack:        6208 kB
PageTables:        10348 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2604884 kB
Committed_AS:    1387404 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       10772 kB
VmallocChunk:   34359722748 kB
HardwareCorrupted:     0 kB
AnonHugePages:    350208 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       71680 kB
DirectMap2M:      976896 kB

8.6.15 mdb ::memstat

  • Solaris のメモリ使用状況の高水準の分析を表示する

8.6.16 kstat

  • 他のツールが表示できる統計は、いずれも kstat で参照できる
    • 読み書きのページキャッシュ統計( kstat -n segmap
    • iノードキャッシュ統計( kstat -n inode_cache
    • など
  • 豊富な情報を得られるが、伝統的にドキュメントされていない

8.6.17 その他のツール

8.6.18 ビジュアライゼーション

  • ファイルシステムレイテンシの分布は、二峰的になることが予想される
    • レイテンシのの低いところにファイルシステムキャッシュヒットのピークが現れ、高いところにキャッシュミス(ストレージデバイスI/O)のピークが現れる
    • なので、分布を平均や最頻値、中央値などのひとつの値で表現すると誤解を招きやすい
  • 完全な分布を示せるビジュアライゼーションの方法としてはヒートマップなどがある
    • x軸で時間の経過、y軸でI/Oレイテンシを表す

8.7 実験

  • ファイルシステムのパフォーマンスをアクティブにテストするツールについて。
  • これらのツールを使うときには、ディスクに届いているワークロードが予想通りのものになっていることを確認するため、iostat(1) を実行したままにするとよい。
    • たとえば、ファイルシステムキャッシュに簡単に収まりきる程度のワーキングセットサイズをテストするときには、読み出しワークロードは100%キャッシュヒットすると予想されるので、iostat がディスクI/Oを表示することがあってはならない。

8.7.1 アドホックテスト

  • dd(1) コマンド(デバイス間コピー)を使用して、シーケンシャルファイルシステムのパフォーマンスのアドホックテストを実行できる
  • file1という名前の1GBのファイルを1MBのI/Oサイズで書き込んでから読み出すコマンド実行は以下。
$ dd if=/dev/zero of=file1 bs=1024k count=1k
1024+0 records in
1024+0 records out
1073741824 bytes transferred in 2.492904 secs (430719292 bytes/sec)
$ dd if=file1 of=/dev/null bs=1024k
1024+0 records in
1024+0 records out
1073741824 bytes transferred in 1.649736 secs (650856692 bytes/sec)

8.7.2 マイクロベンチマーキングツール

  • Bonnie, Bonine++
    • 単一のスレッドからの単一のファイルに対する複数のワークロードをテストする単純なプログラム
  • fio
    • 高度な機能を多数含むカスタマイズ可能なファイルシステムベンチマークツール
    • 現実に起きるアクセスパターンを他の方法よりも正確にシミュレートできる(非一様ランダム分布)
    • レイテンシパーセンタイルの表示が可能
  • FileBench
    • プログラム可能なファイルシステムベンチマークツール
    • ワークロードモデル言語でワークロードを記述することで、アプリケーションのワークロードをシミュレートすることができる

8.7.3 キャッシュのフラッシング

  • Linux には、ファイルシステムキャッシュをフラッシュさせる手段がある
  • これを用いることで、例えばシステムのブート直後のような、キャッシュが “コールドな” 状態を作り出すことができる

8.8 チューニング

8.8.1 アプリケーションレベルの呼び出し

  • posic_fadvise()
    • データをプリフェッチすべきタイミングはいつか・データをキャッシュすべきときはいつか、を判断するためのカーネルへの追加の判断材料とさせることができる
  • madvise()
    • メモリマッピングを操作する
    • カーネルのキャッシングに関する判断をよりよいものにし、パフォーマンスを向上させることができる

8.8.2 ext3

  • マウント時に mount(8) コマンドで手作業でのオプション設定が可能
    • noatime オプションにより、ファイルアクセスタイムスタンプの更新を無効にする、など。
  • tune2fs(8) で tune2fs -O dir_index /dev/hdX とすることで、hashed B-tree を使って大きなディレクトリでのルックアップをスピードアップさせることができる

8.8.3 ZFS

  • ZFSは、ファイルシステムごとに多数のチューニング可能パラメータ(プロパティと呼ぶ)を持っている
  • システム全体を対象として設定できるパラメータ(/etc/system)も持っている
  • 一般的に、最も重要なパラメータはレコードサイズ。アプリケーションのI/Oに合わせたものに設定する(通常は128kbがデフォルト)
    • レコードサイズよりも小さなファイルは、ファイルサイズと等しい動的なレコードサイズが使われ、設定したレコードサイズは適用されないことには注意。

8.9 練習問題

1. ファイルシステムの用語について

  • 理I/Oと物理I/Oの違い
  • ランダムI/OとシーケンシャルI/Oの違い
    • ランダムI/O : 前後のI/Oに関連性がないI/O
    • シーケンシャルI/O : 前のI/Oの末尾から次のI/Oが始まるようなI/O
  • Direct I/Oとは何か
  • ノンブロッキングI/Oとは何か
    • ストレージデバイスに対するI/Oなどにより待ちが発生する際、ブロックしCPUを手放させるのではなくエラーを発生させることでブロックを発生させない方法
  • ワーキングセットサイズとは何か
    • 一度に読み出すデータのサイズ。これが小さいと、全てがファイルシステムキャッシュに乗りやすくなる

2. コンセプトについて

3. その他

  • O_SYNC ではなく f_sync() を使うメリットは何か
    • O_SYNC を指定してファイルをオープンした場合、書き込みI/Oは同期的になる。同期書き込みは永続ストレージへの完全な書き込みが終わらなければ完了しない
      • データベースのログライターなどで用いられる
    • f_sync() システムコールを使うことで、コード内のあるチェックポイントでそれまでの非同期書き込みを同期的にコミットできる。同期書き込みをグループ化することでパフォーマンス向上に繋がる。
  • read()/wrtie()と比較したときの mmap() の利点、欠点は何か
  • 理I/Oが物理I/Oになるとふくらむのはどういうときか
  • 理I/Oが物理I/Oになると小さくなるのはどういうときか
    • キャッシュが効いている場合
    • バッファ内の書き換えで済んだ(相殺できた)ような場合
  • ファイルシステムのCOWがパフォーマンスを向上させる仕組みについて
    • コピー操作の後、実際に変更がおこなわれるまで実体の複製はされない


follow us in feedly