> [!abstract] 概要(SoCC '25 abstract の日本語訳) > SSD需要の増大とスケーリングの困難さにより、製造業者はより高性能・高耐久性を約束する新しいSSDインターフェースを模索せざるを得なくなっている。これらのインターフェースは従来の抽象化の硬直性を緩和する一方で、アプリケーションレベルまたはシステムレベルの変更を必要とし、それがシステムの安定性・セキュリティ・移植性に影響を与えうる。さらに悪いことに、そうした変更は次世代インターフェースの登場によって無駄になる。したがって、こうしたインターフェースの採用が限定的にとどまり、open-channel SSD から stream SSD に至るまで、実験的インターフェースの墓場を残してきたのも驚くには当たらない。 > 我々の解決策である Valet は、ユーザー空間のシムレイヤーを活用してアプリケーションデータに配置ヒントを付与し、ファイルシステムに対して最大2〜4倍の書き込みスループットを実現し、アプリケーション固有のソリューションに匹敵するかそれ以上の性能を、最大6倍低いテールレイテンシとともに提供する。Valet は動的な配置ヒントを生成し、アプリケーション・ファイルシステム・カーネルへの変更を一切加えずに、アプリケーションデータを現代的なSSDへ再マッピングする。我々は RocksDB、MongoDB、CacheLib という広く使われているアプリケーション群にわたって、Valet の性能・効率・マルチテナンシー上の利点を実証し、アプリケーション固有ソリューションの性能と、ログ構造化データ集約型アプリケーションへの広い適用性を兼ね備えたソリューションを提示する。 ## 論文情報 - タイトル: Valet: Efficient Data Placement on Modern SSDs - 著者: Devashish R. Purandare、Peter Alvaro、Avani Wildani(UC Santa Cruz)、Darrell D. E. Long(UC Santa Cruz)、Ethan L. Miller(UC Santa Cruz / Pure Storage)。Avani Wildani の所属は Emory University / Cloudflare。 - 媒体: ACM Symposium on Cloud Computing(SoCC '25)、2025年11月19〜21日、オンライン開催 - DOI: [10.1145/3772052.3772256](https://doi.org/10.1145/3772052.3772256) - コード: [github.com/shimplify/valet](https://github.com/shimplify/valet) ## 概要 NANDフラッシュSSDは書き込み単位と消去単位が非対称なため、有効データの再配置(ガーベジコレクション)が性能と寿命を損なう。本論文は、ログ構造化ストレージシステムに焦点を当て、データの affinity(親和性)と lifetime(寿命)という2つの配置戦略でこの問題を緩和できると論じる。既存の Zoned Namespace SSD(ZNS)や Flexible Data Placement(FDP)といったインターフェースはホスト誘導の配置を可能にするが、アプリケーションやファイルシステムの書き換えを要求するため採用が進まない。著者らは、この責務をアプリケーションでもカーネルでもなく、両者の間に位置する userspace の「シムレイヤー」に切り出すべきだと主張し、その実装である Valet を提示する。 ## 問題設定 - 入力: RocksDB・MongoDB(WiredTiger、LSM モード)・CacheLib といった、ログ構造化(append-only)のデータ集約型アプリケーションが発行する標準的な POSIX ファイルシステム呼び出し(open/read/write/fsync/mmap 等)。 - 出力: 現代的SSDインターフェース(ZNS の zone、あるいは multi-stream/FDP 的なヒント)へ変換された配置ディレクティブ、およびそれに基づいて再配置されたデータ。 - 前提条件: アプリケーション・ファイルシステム・カーネルへの変更をゼロにすること。統計的あるいはヒューリスティックにアプリケーションのデータストリームを識別できること。 Table 1(論文本文)は、これまでのホスト誘導データ配置インターフェース(Multi-Stream: 2016年導入、Open-Channel: 2017年、ZNS: 2021年、FDP: 2022年)がいずれも数個のアプリケーションのみで実証されたのち Linux カーネルサポートが Deprecated になる、あるいは対応ファイルシステム・アプリケーションが極めて限定的なまま推移してきたことを示す。 ## 提案手法 - **アーキテクチャ**: Valet は「Application Call Interception(アプリケーション呼び出し横取り)」「Data Placement Engine(データ配置エンジン)」「Device Manager(デバイスマネージャ)」の3コンポーネントからなる。open/close/read/write/fsync/fdatasync/mmap/free などの libc 呼び出しをアプリケーションとカーネルの間で横取りし、Hint Generation → Interface-specific hint conversion という経路でヒントを生成・変換し、必要な場合は valet-mapper が buffering・extent management・garbage collection を担ってデバイスへ書き込む(Figure 3)。 - **アプリケーション呼び出しの横取り(3.1節)**: eBPF・FUSE・WASM・動的ライブラリなど複数のシム手法(Table 2)を比較検討した上で、カーネル境界を追加せず全て userspace で完結する `LD_PRELOAD` を採用した。LD_PRELOAD は静的リンクなし・カーネル変更なし・実行時セットアップのみで、性能劣化が最小(著者らの計測で LD_PRELOAD は1回のシステムコールあたり約2 µs、syscall_intercept は約2 msのオーバーヘッド)。Valet は `dashmap`(Rust の並行ハッシュマップ)で状態(pathMap・fdMap)を管理し、複数スレッドからの同時アクセスによるロック競合を避ける。 - hint-based インターフェース(multi-stream・FDP相当)では valet-mapper 不要で、open() 時に `fcntl()`/`fadvise()` でヒントを発行するだけの軽量な介入で済む。 - host-managed インターフェース(ZNS)では、Valet は valet-mapper へストリーム割り当てを要求し、write/read/close/unlink などの操作を valet-mapper 経由で仲介する軽量な仮想ファイルシステムとして振る舞う。 - `mmap()` のような in-place 更新を要求する呼び出しは host-managed モードでは非対応とし、LOCK ファイルやマニフェストなど in-place 更新が必要な少量のファイル(ログ構造化システムでは操作の1%未満)を、valet-mapper がランダム書き込み向けの通常ゾーンへ振り分ける。 - **データ配置エンジン(3.2節)**: Valet は temperature ベースの粗いヒント(RWH_HINT の hot/cold/warm/undefined の4値、f2fs でのみ対応)を超える抽象化として、stream(単一の論理的な書き込み元、例: write-ahead log・data log・compaction)と、その中の時間的な部分集合である lifetime-group(Figure 4)を導入する。ストリームの識別は (1) ヒューリスティック(RocksDB のようにファイル拡張子・配置場所で WAL と SST を区別できる場合)と、(2) 自動化(Valet-Learn、バッチ型 mini KMeans でファイルオープン時の特徴からストリームをオンライン推定)の両方をサポートする。`get_hint()` API がリゾルバを介して、multi-stream ヒント・ZNS 用ゾーン・placement identifier(FDP、未実装)のいずれにも変換可能な内部表現を提供する。 - **valet-mapper(Device Manager, 3.3節)**: ZNS 上に自前の軽量ストレージエンジンを実装し、zonefs(カーネルのゾーンデバイスラッパー)を介してシステムコールでゾーンを操作する。ストリームをゾーンに1対1でマップし、4 KiB〜512 KiBのブロック整列 extent 単位でデータを管理する(allocate-on-flush)。write buffering はゾーン単位の write-through バッファで実装し、ガーベジコレクションは「lazy」戦略で、あるゾーンの全 extent が削除済みとマークされた時点でデータ移動なしにゾーンをリセットする(データ移動を要する再配置は、空きゾーンが閾値を下回った場合のみ発生)。クラッシュ一貫性は、fsync/fdatasync/close 時にバックアップ領域へメタデータを書いてからアトミックにコミットする方式で担保する。 **Figure 3: Valet の簡略化アーキテクチャ** ![[_attachments/2026_Unknown_Valet_Efficient_Data_Placement_Modern/fig03-valet-architecture.png]] (Figure 3. Valet はアプリケーション呼び出しを横取りし、配置プランを生成し、それをプロトコルへ解決した上でデータ配置を管理する。Intercepted APIs(open/close, read/write, fsync/fdatasync, mmap/free)を Placement Logic(Hint Generation → Interface-specific hint conversion)に渡し、Device Manager(buffering, extent management, garbage collection)がカーネル境界の上でデータを扱う。Source: 論文 Figure 3 を再現。) **Figure 4: streams と lifetime-groups による配置ヒントの構造** ![[_attachments/2026_Unknown_Valet_Efficient_Data_Placement_Modern/fig04-streams-lifetime-groups.png]] (Figure 4. Valet のヒントは affinity(stream: Write-Ahead Log / SSTables / Checkpoints)と lifetime(各 stream 内の lifetime-group、例: WAL は lifetime-group 1 と 4)の2軸で組織化される。Source: 論文 Figure 4 を再現。) ## 新規性 - 既存のホスト誘導配置インターフェース(ZNS・FDP など)は、応答すべきレイヤー(アプリケーション or ファイルシステム)を巡って行き詰まっていた。アプリケーション書き換え(zenfs のような)は工数が大きく、API変化のたびに陳腐化し(zenfs は最新の RocksDB で既に動作しない、2023年10月以降コミットがほぼ止まっている)、可搬性を損なう。ファイルシステム側の対応(f2fs)はカーネル内での変更のため更新が困難で、アプリケーション固有のセマンティクス(affinity・lifetime)を捉えられない。 - Valet はこの二者択一を回避し、アプリケーション・カーネルいずれも変更しない userspace シムレイヤーという「第三の道」を提示する。これにより、複雑さをアプリケーションとファイルシステムから切り離した監査可能な小さいモジュールに閉じ込め、カーネル内コードの肥大化(バグ・攻撃対象領域の増大)を避けつつ、アプリケーション固有チューニングに匹敵する性能を得る。 - temperature ベースの粗い分類ではなく affinity と lifetime を配置の一般理論として定式化した点、ヒューリスティックと学習ベース(Valet-Learn)の両方のヒント生成を同一アーキテクチャの上で実証した点も新規性として述べられている。著者らは、3アプリケーション×2インターフェース種別(ZNS・カーネルヒント)にわたる評価は、従来のいずれの取り組みよりも広いという。 ## 実験設定 - ハードウェア: 64コア AMD EPYC 7452、128 GB DRAM。Western Digital Ultrastar DC ZN540(4 TB、ZNS 対応)を2台使用。 - ソフトウェア: Ubuntu 22.04、Linux kernel 6.5。各対象システムは最新安定版を使用し、付属ベンチマークツールをそのまま利用。 - 比較対象: f2fs(zns 対応ファイルシステム)、zenfs(RocksDB 専用の ZNS バックエンド、アプリケーション固有ソリューションの代表としての「gold standard」)。btrfs の ZNS サポートは限定的でベンチマークが動作せず、Persimmon は対応カーネルが古く(5.18)評価不能だったため比較から除外。 - ケーススタディごとのベンチマーク: - **RocksDB**(db_bench): 1億操作、20 Bキー・400 B値、fill(sequential/random)、read(sequential/random)、read-while-writing、overwrite。FIFO コンパクションを使用(時間的分離を自然に与えるため)。 - **MongoDB**(WiredTiger、LSM モード): wt-perf の medium サイズ LSM ツリーテスト。マルチスレッド read/update/read-and-update。 - **CacheLib**(cachebench): 128 MB のインメモリキャッシュ(意図的に小さくしてフラッシュへのスピルオーバーを誘発)で1000万回の get/set 操作。 - 評価指標: スループット(GB/s または K ops/s)、レイテンシ分位点(p50〜p99.99)、CPU時間の内訳(perf によるプロファイリング)、ガーベジコレクション回数・移動データ量・空き容量、メモリ使用量(heaptrack)、追加コード行数。 ## 実験結果 - **動機付け実験(2節)**: zonefs 上への書き込み(各ファイルを個別ゾーンへマップする軽量マッピング層)はデバイスの全帯域を引き出せたが、f2fs はスレッド数1〜14において帯域の30〜50%に留まった(Figure 1)。CPU時間の内訳では f2fs は同期(sync)に34.43%、fio呼び出しに12.72%を消費し、zonefs は72.25%を fio に還元できていた(zonefs 10.25% write / 17.5% sync / 72.25% fio、f2fs 12.72% write / 34.43% sync / 49.72% fio、Figure 2)。 - **RocksDB(Figure 5・6)**: fill/overwrite で Valet は f2fs に対して2倍超の改善を示し、zenfs に匹敵する性能を得た。read では Valet は f2fs・zenfs いずれとも同等。テールレイテンシは p99.99 で Valet が約20 µs、zenfs が約555 µs と大きく優位(readahead() の横取りとプリバッファリングによる)。Valet-Learn はオンライン学習ゆえ小さいオーバーヘッドを持つが、p99.9のテールレイテンシでも十数 µs程度に留まり、f2fs・zenfs を上回る。 - **なぜ Valet が速いか(4.1.1節、Figure 7)**: perf の分析では f2fs は WAL の永続化に数十ミリ秒を要し、ロック・メタデータ更新・キャッシュのアロケーション/解放でCPU時間の44%を消費するのに対し、Valet はバッファのコピーと定期的な永続化のみで、userspace オーバーヘッドはプログラム時間の27%未満(zenfs と同水準)。 - **MongoDB/WiredTiger(Figure 8・9)**: Valet はマルチスレッド read で f2fs の4倍超のスループット、書き込み主体のワークロードで3倍のスループットを達成。WiredTiger のログ書き込みは `mmap()` を使うため valet-mapper の in-place 更新非対応の制約に抵触するが、この部分はランダム書き込み領域(LOCK ファイルと同様の扱い)で処理する。レイテンシは f2fs がほぼ全操作で200 µsを超えるのに対し、Valet(および Valet-Learn)は100 µs未満に収まる。 - **CacheLib(Figure 10)**: Valet はスループットで8%の改善(56.8 KOps/s 対 f2fs の52.3 KOps/s)と、特に p90 以上での読み取りレイテンシの大幅な削減を示した。改善が小さい理由は、CacheLib の Navy エンジンが io_uring を用いて既にファイルシステムオーバーヘッドの多くを回避しているため。 - **マルチテナンシー(4.4節、Figure 11)**: RocksDB と MongoDB(WiredTiger)を同一デバイス上で同時実行(4つの並行ライタ)させた場合、f2fs はテールレイテンシ(p99.9・p99.99)で書き込みが約2倍まで悪化したのに対し、Valet はデバイスバッファ・領域を分離マッピングすることで劣化が小さかった。著者らは、zenfs はそもそも複数テナントに対応できず、データセンター適用性が大きく制限されると指摘する。 - **オーバーヘッド(4.5節)**: 書き込みアンプリフィケーション実験(Table 3)では、Valet は空き容量確保時にデータを一切移動せず(WAL ブロックの速い解放のため)、f2fs は1059 MiB のデータを移動した(GC呼び出し回数は Valet 8回・f2fs 4回、実験終了時の空き容量は Valet 48.2 GiB・f2fs 33.2 GiB)。デバイス書き込みアンプリフィケーション係数はいずれも1(f2fsとzenfs相当)。メモリ使用量は32 MBバッファ×2ストリームで64 MB程度が主要な使用量であり、heaptrack でのピーク実測は73 MB(f2fsの同条件でのメモリ使用量200 MBより小さい)。追加コード行数(Table 4)は zenfs がアプリケーション側4017行+userspace 988行、f2fs(zns) がカーネル側38,188行+userspace 1252行に対し、Valet はカーネル・アプリケーション側の変更ゼロでuserspace 1700行のみ。 **Figure 1: zonefs と f2fs のスループット・レイテンシ比較(動機付け実験)** ![[_attachments/2026_Unknown_Valet_Efficient_Data_Placement_Modern/fig01-zonefs-vs-f2fs-throughput.png]] (Figure 1. zonefs への書き込みはスレッド数1〜14全域でデバイスの全帯域を引き出せるが、f2fs は帯域・レイテンシとも劣化する。Source: 論文 Figure 1 を再現。) **Figure 5: RocksDB(db_bench)のスループット** ![[_attachments/2026_Unknown_Valet_Efficient_Data_Placement_Modern/fig05-rocksdb-throughput.png]] (Figure 5. fill sequential/random・overwrite・read while writing・read random・read sequential の各ワークロードでの F2FS・ZenFS・Valet・Valet-Learn のスループット比較。fill 系では Valet が f2fs の2倍以上、read 系ではおおむね同等。Source: 論文 Figure 5 を再現。) **Figure 8: WiredTiger(MongoDB)のスループット** ![[_attachments/2026_Unknown_Valet_Efficient_Data_Placement_Modern/fig08-wiredtiger-throughput.png]] (Figure 8. update/read/read and update/fill の各ワークロードで、ログとLSMファイルの物理的分離により Valet が f2fs に対して大幅に高速な書き込み・更新を達成することを示す。Source: 論文 Figure 8 を再現。) ## 考察 - Valet の性能優位性は、根本的にはカーネル内ファイルシステムが担う同期・ロック・メタデータ更新のオーバーヘッドを userspace 側の単純なバッファコピーへ置き換え、かつアプリケーション固有のデータ関係(WAL vs SST など)を明示的なストリーム分離としてデバイスに伝達できる点に由来する。zenfs のようなアプリケーション固有ソリューションと同等以上の性能を、RocksDB 以外のアプリケーションにも変更なしで適用できる汎用性と両立させたことが Valet の中心的な主張である。 - Valet-Learn は多くのケースで手動チューニングに匹敵する性能を達成しつつ、予測エンジンに起因する小さなテールレイテンシのスパイクを抱える。これは自動化と性能のトレードオフとして著者らも明示的に認めている。 - 著者らは、ホスト誘導データ配置インターフェースの歴史(Table 1)が「新インターフェースが登場し、少数アプリケーションで実証され、数年で廃れる」という繰り返しパターンを示していると総括し、これを打破するには配置の複雑さをアプリケーションやファイルシステムから切り離す必要があると論じる。 ## 強み / 弱点・課題 - **強み**: - アプリケーション・ファイルシステム・カーネルへの変更ゼロで、RocksDB・MongoDB・CacheLib という異なる特性を持つ3つのシステムに同一アーキテクチャを適用できた(適用範囲の広さは著者らが「これまでのどの取り組みよりも広い」と主張する根拠)。 - ヒューリスティックと学習ベースの双方のヒント生成をプラガブルに切り替えられる設計により、将来的な機械学習ベースの分類やドメイン固有ヒューリスティックへの拡張が容易(5節 Related Work で LLM ベース分類への言及もある)。 - 追加コード行数(Table 4)がカーネル変更ゼロ・userspace のみ1700行と、比較対象(zenfs・f2fs(zns))より大幅に小さく、監査可能性・保守性の観点で優位。 - **弱点・限界(3.4節)**: - LD_PRELOAD の限界を継承する。静的リンクされたアプリケーションは横取りできない。Golang や Java のように libc を使わない言語で書かれたシステムはこの手法で対応できず、別のシム手法が必要になる。fork-exec や複数プロセスが協調する複雑なクライアント・サーバアプリケーションでは、preload が意図通り効かないケースがある。 - valet-mapper のスコープはログ構造化 append-only アプリケーションに限定される。in-place 更新や mmap 書き込みに依存するデータ構造は valet-mapper を利用できず、ファイルシステムへパススルーされる(ヒントの発行自体は可能だが物理配置の恩恵は得られない)。 - valet-mapper が管理するファイルは、Valet を介さないサードパーティのバックアップ・コピーユーティリティからは見えない。valet-mapper はファイルシステムの完全な代替ではなく、アクセス制御やロッキングのようなファイルシステム機能は限定的にしかサポートしない。 - FDP(Flexible Data Placement)のサポートは、対応ハードウェアが一般に入手できないことと、ディレクティブが NVMe I/O 経由でしか提供されない設計上の制約から、将来課題として位置づけられ本論文では未実装。