Upgrade to Pro — share decks privately, control downloads, hide ads and more …

仮想ファイルシステムを導入して開発環境のストレージ課題を解消する

 仮想ファイルシステムを導入して開発環境のストレージ課題を解消する

CEDEC 2024 にて講演した『仮想ファイルシステムを導入して開発環境のストレージ課題を解消する』の資料です。

株式会社セガ 開発技術部 山田 英伸
株式会社セガ 第3オンライン研究開発プログラム1部 高橋 陸
株式会社セガ フェイブ AMインフラ研究開発部 阿部輝仁

SEGADevTech

August 27, 2024
Tweet

More Decks by SEGADevTech

Other Decks in Programming

Transcript

  1. 2 ©SEGA 自己紹介 株式会社セガ 技術本部 開発技術部 山田 英伸 SEGA入社後、業務用ゲームタイトルの下回りライブラリ開発やツール 作成などに従事。現在は、特定の専門分野を持たず、幅広い領域で色々

    とやっています 講演歴 - Unite Tokyo 2019 「大量のアセットも怖くない~HTTP/2による高速な通信の実装例」 - CEDEC 2021 「ダウンロード時間を大幅減!~大量のアセットをさばく高速な 実装と運用事例の共有~」
  2. 6 ©SEGA • 3分でわかる講演の要点 • 仮想ファイルシステムとは • ProjFS と SlimSync

    • 『PSO2 ニュージェネシス』開発環境での効果 • ProjFS の組み込み TIPS • まとめ アジェンダ
  3. 9 ©SEGA • 「SlimSync」: リポジトリ同期ツール – Windows用 仮想ファイルシステムを活用 – バージョン管理下の全ファイルが「ある」ように見える

    ツールを開発 リポジトリからのデータ取得を仮想ファイルシステムによって オンデマンド化&シームレス化し、開発者のリポジトリ同期に 要する時間やストレージ容量を節約するツール
  4. 14 ©SEGA • 「仮想ファイルシステム」でイメージするもの – 仮想マシンの “仮想ハードディスク” – Unix系OSのVFS (Virtual

    File System) – 仮想ファイルを扱うもの • ネットワーク越しに扱うもの – NFS, CIFS, クラウドストレージなど 仮想ファイルシステムとは
  5. 15 ©SEGA • Unix系 VFS の場合 – 普段は一番上の状態を見ている – 各ディレクトリの

    ファイルシステムを気にしない 仮想ファイルシステムとは ext4 proc Virtual File System xfs Disk Disk /home /var /proc
  6. 17 ©SEGA • Windows特有で使えるもの – Projected File System API –

    Cloud File API • ファイルの存在を見せること、 データ本体を切り離すこと、を実現 仮想ファイルシステムとは File Data File Data Data 本講演では、これらに対して 仮想ファイルシステムと呼びます
  7. 18 ©SEGA • データ(ファイル)は – ユーザーによって必要な範囲が変わる – 全ファイルが必要なことは稀 仮想ファイルシステムが効果的な理由 File1

    File2 Data Data File3 Data File4 Data File1 File2 File3 Data File4 Data Data Data ユーザー1 ユーザー2 つかう分だけデータ実体があればよい!
  8. 19 ©SEGA • データ本体がない状態でも、必要になったら”自動”で取得 仮想ファイルシステムが効果的な理由 File1 File2 Data Data File3

    Data File4 Data ユーザー File5 File6 Data File7 Data File8 Data Data Data Data Data 全てが揃っているように見えて、 必要な分だけのデータでストレージ消費を最小化 アクセスの瞬間で中身を取得 (実体化)
  9. 21 ©SEGA • ProjFS を採用 – ファイル/ディレクトリの外観が使用前後で変化しない – 安定した環境ならProjFSは高速 ProjFS

    と Cloud File API OS標準 速度 異常状態への 対応 その他 ProjFS 〇 ◎ × GVFS(Git Virtual File System)は ProjFS の先祖 C#ラッパーがある Cloud File API 〇 ▲ 〇 クラウドストレージに対応した仮想ファイル機 能を提供
  10. 22 ©SEGA • Windows10 (1803) にてProjFSの可能性を予見(動作をチェック済) – https://learn.microsoft.com/ja-jp/windows/win32/projfs/projected-file-system • Virtual

    Sync: Terabytes on Demand (GDC2022 / Bungie, Inc) 講演 – https://www.gdcvault.com/play/1027699/Virtual-Sync-Terabytes-on • 『NGS』 開発チームと前述の講演をきっかけに協力体制 ProjFS採用の理由
  11. 23 ©SEGA • Git Virtual File System: GVFS – 2018年ごろに話題

    – Team Foundation , Azure DevOps Server が必要 – 現在は “VFS for Git” (ただしメンテナンスモード) 余談
  12. 24 ©SEGA User Mode Kernel Mode 初期化: PrjStartVirtualizing() • 仮想化を開始するパスを設定

    • 各処理のコールバックを登録 ProjFS APIの使い方 指定フォルダー配下の特定 I/O 要求のみ転送 D:¥my-project¥ ProjFS [Provider] StartEnumeration GetPlaceholderInfo GetFileData : ProjFS [System] StartEnumeration GetPlaceholderInfo GetFileData :
  13. 25 ©SEGA User Mode Kernel Mode 初期化: PrjStartVirtualizing() • 仮想化を開始するパスを設定

    • 各処理のコールバックを登録 ProjFS APIの使い方 指定フォルダー配下の特定 I/O 要求のみ転送 D:¥my-project¥ ProjFS [Provider] StartEnumeration GetPlaceholderInfo GetFileData : ProjFS [System] StartEnumeration GetPlaceholderInfo GetFileData : PrjFillDirEntryBuffer() PrjWritePlaceholderInfo () PrjWriteFileData()
  14. 26 ©SEGA • ProjFS制御下では、ファイルは以下の状態を遷移 ファイルの状態変化 項目がDisk上にない. アイテム列挙に出現 FindFirstFile, readdir など

    項目はDisk上に存在. メタデータのみで、 ファイル内容はカラ オープン操作 CreateFile, fopen など 項目はDisk上に存在. ファイル内容が ストレージ上に存在. 読み取り操作 ReadFile, fread など Hydratedな状態から ファイル内容が変更 書込み操作 WriteFile, fwrite など Virtual Placeholder open read Hydrated Full
  15. 27 ©SEGA • ProjFS制御下では、ファイルは以下の状態を遷移 ファイルの状態変化 Virtual Placeholder Hydrated Full open

    仮想状態 実体化 ストレージを消費する範囲 項目がDisk上にない. アイテム列挙に出現 項目はDisk上に存在. メタデータのみで、 ファイル内容はカラ 項目はDisk上に存在. ファイル内容が ストレージ上に存在. Hydratedな状態から ファイル内容が変更 read write
  16. 29 ©SEGA User Mode Kernel Mode • ドライバ間に、フィルタドライバーが挿入可能 – ProjFSはフィルタドライバーの1種

    • ProjFSを使うと ユーザーモードのプログラムとして実装 ProjFSの仕組み ProjFS ドライバー NTFS ファイルシステムドライバー エクスプローラー など ランタイムライブラリ ファイルシステムドライバー ストレージクラスドライバー HDD/SSD ProjFSを利用した実装 ・列挙情報 ・ファイル内容操作 .... Callback I/Oリクエスト データ
  17. 30 ©SEGA ProjFSの仕組み (例:リポジトリ投影) Callback ProjFS ドライバー NTFS ファイルシステムドライバー エクスプローラー

    など ランタイムライブラリ ファイルシステムドライバー ストレージクラスドライバー HDD/SSD project/ • main/ • Readme.txt ストレージより project/ • branch-a/ • License.txt リポジトリ情報より 上層に見せる情報を収集 投影元へのアクセスなど project/ • branch-a/ • License.txt • main/ • Readme.txt ProjFS マージ結果
  18. 32 ©SEGA • ProjFSは NTFS (NT File System)の機能を活用 – リパースポイント

    (再解析ポイント) • シンボリックリンクやジャンクションなど – ファイルやフォルダを区別しないエントリ形式 ProjFSの仕組み (下位ファイルシステム側) ※ リパースポイントがキー要素なので、ReFSでも使用可能
  19. 33 ©SEGA • 一般的なファイルの格納状態 ProjFSの仕組み (下位ファイルシステム側) HEADER MFT $MFT $MFTMirr

    ... File File MFTエントリ情報 ファイルエントリ情報 Attr: $STANDARD_INFORMATION Attr: $FILE_NAME Attr: $DATA (Non-Resident) Cluster: File Data Cluster: File Data Cluster: File Data Data Run List Disk / Volume Volume内クラスタを示す ファイル 内容
  20. 34 ©SEGA • リパースポイントがある場合 (IO_REPARSE_TAG_PROJFS) ProjFSの仕組み (下位ファイルシステム側) HEADER MFT $MFT

    $MFTMirr ... File File MFTエントリ情報 ファイルエントリ情報 Attr: $STANDARD_INFORMATION Attr: $FILE_NAME Attr: $REPARSE_POINT Disk / Volume Attr: $DATA (Non-Resident) Data Run List 実体化のタイミングで構成 Cluster: File Data Cluster: File Data Cluster: File Data ファイル 内容 Data Run List
  21. 36 ©SEGA • ProjFSを使用したSlimSyncというツールを開発 – バージョン管理システム Perforce と接続 – 開発言語はC#を用いて実装

    • ProjFS APIはWin32API • C#によるラッパーライブラリを使用 – GDC2022講演でも触れられていたMicrosoft製 – https://github.com/microsoft/ProjFS-Managed-API 設計事例 現在は”Helix Core” 講演内は馴染み深い Perforce で表記
  22. 39 ©SEGA Repository Backend SlimSync構造図 (ファイルシステムプロバイダ側) SlimSync Main [SYSTEM] File

    Request Perforceアダプター Perforce (Depot) ProjFS Callback処理部 他リポジトリ用 アダプター Repository Web Server (Kestrel) Client Web Debug Console Debug gRPC 制御 gRPC
  23. 42 ©SEGA 『ファンタシースターオンライン2』(=PSO2)とは 2012年7月にサービス開始されたセガのオンラインアクションRPG 「無限の冒険」「オンラインRPG最高峰のアクション」 「究極のキャラクタークリエイト」「境界を超えるRPG」 をコンセプトに長期運営(今年で12周年!) 2021年6月にグラフィックエンジンを一新し、大幅リニューアルしたのが、 『ファンタシースターオンライン2 ニュージェネシス』(=NGS)

    超大型アップデートにより『PSO2』から1000年後の世界をオープンフィールドで実現。 『PSO2』の世界はそのままプレイ可能で、セーブデータも共有し 同じキャラクターで、『PSO2』と『NGS』の世界を自由に行き来できるのが最大の特徴。 【対応プラットフォーム】PC、PS4、Xbox One、Switch(クラウド) 『PSO2 ニュージェネシス』とは?
  24. 44 ©SEGA • 既に運用中のタイトル – 開発に影響がでる変化はNG • 仮想ファイルシステム(ProjFS)は 開発PCごとに使用の有無が設定可能 –

    チーム全体への影響が極めて少ない – 開発PC上で動作するので、 Perforceサーバー側の変更不要 – JenkinsエージェントをSlimSyncに置き換えて検証 『NGS』で検証するにあたって
  25. 45 ©SEGA • 1ブランチのデータ量 – 全体 ▪ 1.09TB – コード

    ▪ 約50,000ファイル – アセット ▪ 約1,200,000ファイル ▪ 約800GByte 『NGS』のブランチ戦略
  26. 50 ©SEGA • オンデマンドのため、時間の掛かり方が変化 リポジトリ同期のコストに対する補足 sync begin sync end Perforce

    FILE1 転送 FILE1 保存 FILE2 転送 FILE2 保存 FILE3 転送 FILE3 保存 FILE2 open FILE2 read sync begin sync end slimsync FILE2 転送 FILE2 保存 FILE2 open FILE2 read リビジョン管理 リビジョン管理 メリット: sync end までが速い デメリット: open から read までが遅い(※) メリット: 転送量が少ない メリット: 占有量が少ない
  27. 53 ©SEGA • ワークスペースマッピングの設定方法 o 1行につき1つのマッピングで構成 o フォルダ単位での除外やファイルの除外 o ディポシンタックスに一致するファイルの除外

    検証②ストレージの使用量について //depot/... //work/... -//depot/main/... //work/main/... //depot/main/source/... //work/main/source/... //depot/main/data/... //work/main/data/... //depot/main/asset/....json //work/main/asset/....json ※実際に使用されている設定とは異なります。
  28. 56 ©SEGA • アセットビルドマシンのストレージ使用量 • アセットの特徴 – 最新のブランチで使用するアセットは限られている • 『PSO2』のアセットで直近5ブランチで使用されたファイルは100MB未満

    – バージョンごとに分かれておらず、新旧のデータが入り乱れている – 古いアセットも再利用や不具合修正のため必要になることがある 検証②ストレージの使用量について SlimSync有無 使用量 ブランチ全体に 対する割合 無効 1045.72GiB 98% 有効 167.3GiB 15%
  29. 62 ©SEGA • 仮想化によって効率的になる部分があった – 作業始めの時間は明らかに短縮 – ストレージの実質的な使用量は削減 • 環境によっては効果が出せないケースも存在している

    – 使用しているエンジンやツールとの相性 – 役割ごとに綺麗にファイルが分けられている場合 • ワークスペースマッピングによる制限が不要になる – 細かなマッピングが不要になり 設定する労力の削減や設定ミスにる不具合の防止が可能 検証まとめ
  30. 65 ©SEGA Perforce によるエンコーディング変換の概略 事象: ファイル末尾が欠落する 知識 TXT Perforce リポジトリサーバー

    データベース TXT クライアント ワークスペース クライアント設定 (エンコーディング指定) クライアント ファイルタイプと クライアント設定に応じた 文字コード・改行コード エンコーディング変換 (ファイルサイズ増大) ローカルストレージ リポジトリ/ディポ ファイルはすべて↓で保存 • 文字コード=UTF8 固定 • 改行コード=LF 固定 ファイルタイプ (エンコーディング指定) UTF8/LF SJIS/CRLF SlimSync ツール
  31. 66 ©SEGA 原因は ファイルサイズの認識のズレ 対応策 • VCS 側のエンコーディング変換機能を回避 • ファイルオープン時に先行取得してサイズ確定

    ↓ 事象: ファイル末尾が欠落する 対策 Virtual Placeholder Hydrated open read Full write フォルダー列挙 ファイルオープン ファイルリード バイナリファイル時 p4 dirs (何もしない) p4 print テキストファイル時 p4 dirs p4 print p4 print
  32. 68 ©SEGA IDisposable インターフェース 事象: ファイルの先頭が破損する 知識 using (FileStream fs

    = File.Create("README")) { AddText(fs, "Hello."); } FileStream fs = File.Create("README"); AddText(fs, "Hello.");
  33. 69 ©SEGA 原因は初歩的な リソースリーク 事象: ファイルの先頭が破損する 対策 using (var content

    = _virtualizationInstance.CreateWriteBuffer(length)) { GetFileContent(...); hr = _virtualizationInstance.WriteFileData(...); } var content = _virtualizationInstance.CreateWriteBuffer(length); GetFileContent(...); hr = _virtualizationInstance.WriteFileData(...); 実体は IWriteBuffer で これは IDisposable
  34. 71 ©SEGA ProjFS におけるテーブルマージのルール 事象: 大文字/小文字が正しくない 知識 ProjFS ドライバー NTFS

    ファイルシステムドライバー エクスプローラー など ランタイムライブラリ ファイルシステムドライバー ストレージクラスドライバー HDD/SSD my-project/ • main/ • Readme.txt ストレージより my-project/ • MAIN/ • License.txt プロバイダより my-project/ • main/ or MAIN/? • License.txt • Readme.txt ProjFS マージ結果 微妙に違う… どうなる…?
  35. 72 ©SEGA 原因は ”正しい”エントリー名の規定の不足 事象: 大文字/小文字が正しくない 対策 リポジトリサーバー SlimSync ツール

    クライアント "D:¥my-project¥Main¥dev¥UEproject¥fpsgame" "D:¥my-project¥main¥dev¥ueproject¥FPSGame" リポジトリ情報を参考に パスを正規化する データベース
  36. 75 ©SEGA 環境変数 PATH の解決処理 事象: OS が不安定になる 知識 20

    個のパスが登録されていれば、1 回のローディングにつき 最悪 20 回の I/O アクセスが こっそり発生
  37. 76 ©SEGA 原因は 遅延ローディングとパス解決 によるデッドロック 対策案 • 遅延ローディングの徹底排除 • SlimSync

    ツールからのワークスペース参照禁止 事象: OS が不安定になる 対策 DLL 起動 DLL DLL をサーチ 未ロード 仮想化開始! アクセス パス解決 遅延ロード DLL 未ロード のまま
  38. 78 ©SEGA 独自のコンテンツキャッシュ仕様 • 初見のファイルはキャッシュフォルダーに溜め込む • ファイル名はリポジトリハッシュから一意に決定 今回実装したロジック 事象: 作業途中で進行停止する

    知識 キャッシュの 存在確認 コンテンツ 取得 キャッシュ Read キャッシュ Read キャッシュ Write : キャッシュヒット時 : キャッシュミス時
  39. 79 ©SEGA 事象: 作業途中で進行停止する 知識 存在確認 取得 Read Write 1つめのスレッド:

    (キャッシュミス) 存在確認 取得 Read Write 2つめのスレッド: (キャッシュミス) Read 存在確認 3つめのスレッド: (キャッシュヒット) オープンエラー/ オープン時にデッド ロック 書き込み先フォルダーに同名ファイルがある ↓ 暗黙の DeleteFile() が発生
  40. 80 ©SEGA 原因はマルチスレッド対応での 排他ロック不足 C# ではアノテーションが利用可能 事象: 作業途中で進行停止する 対策 キャッシュの

    存在確認 コンテンツ 取得 キャッシュ Read キャッシュ Read キャッシュ Write GetFileContentCache(): 再入 NG [MethodImpl(MethodImplOptions.Synchronized)] public bool GetFileContentCache(...) {
  41. 81 ©SEGA 事象: ファイルオープンに失敗する 課題 コンパイル 問題なし! SlimSync ツールに ツール自身からの

    アクセスが到達してる… デッドロック回避処理による File Not Found だ… SlimSync ツールは 直接ファイルアクセスしない 設計なのに…???
  42. 82 ©SEGA パスを扱う “Path” クラス 事象: ファイルオープンに失敗する 知識 string path1

    = @"mydir"; string path2 = @"¥mydir"; string fullPath; fullPath = Path.GetFullPath(path1); Console.WriteLine("GetFullPath() returns ‘{0}'", fullPath); // GetFullPath() returns 'C:¥temp¥Demo¥mydir’ fullPath = Path.GetFullPath(path2); Console.WriteLine("GetFullPath() returns ‘{0}'", fullPath); // GetFullPath() returns 'C:¥mydir' string path1 = "C:/Program Files/Common Files"; string path2 = "C:/Program Files/Microsoft"; string relPath; relPath = Path.GetRelativePath(path1, path2); Console.WriteLine("GetRelativePath() returns ‘{0}’”, relPath); // GetRelativePath() returns ‘../Microsoft’ Path.GetFullPath() Path.GetRelativePath()
  43. 83 ©SEGA Windows ファイルシステムの古い仕様(8.3 形式) 事象: ファイルオープンに失敗する 知識 Path クラスは

    短縮ファイル名にも対応している 一部メソッドは 短縮ファイル名を展開する その際、ディレクトリエントリーを読み出す 短縮ファイル名を 持つエントリー
  44. 84 ©SEGA 原因は Path クラスによる 短縮ファイル名の展開 の試行 対応策 • ~

    記号を含まないルールでのリポジトリ運用 • Path クラスのクローン実装による代替(特に下記) GetFullPath() GetRelativePath() 事象: ファイルオープンに失敗する 対策
  45. 85 ©SEGA • 使い方の不備があると Windows に波及することも • "ProjFS を使うこと" =

    "OS をハックすること" → 地道で綿密な作業の連続 TIPS まとめ