Skip to content

perf: buffer WebGL stream writes until flush - #71

Draft
kochounoyume wants to merge 1 commit into
mainfrom
feature/buffer-webgl-stream-writes
Draft

perf: buffer WebGL stream writes until flush#71
kochounoyume wants to merge 1 commit into
mainfrom
feature/buffer-webgl-stream-writes

Conversation

@kochounoyume

Copy link
Copy Markdown
Member

概要

WebGL の LSStream / IDBStream で、Write のたびに累積データ全体を永続化していた実装を、メモリ上でバッファリングして Flush / Dispose 時にまとめて永続化する方式へ変更します。公開 API のシグネチャは変更しません。

発生していた問題

従来は各 Write ごとに、それまで書いた全バイト列を LocalStorage / IndexedDB へ保存していました。N個のチャンクを書き込むと永続化する総量は概ね 1 + 2 + ... + N となり、累積バッファ全体のコピー、Base64変換と JavaScript bridge、IndexedDB の open / transaction / write が繰り返されます。小さいチャンクを多数書くほど write amplification が大きくなります。

修正内容

  • 書き込みデータを managed memory に保持
  • 容量不足時は指数的に拡張し、毎回の再確保を抑制
  • dirty state を導入し、未変更時の不要な永続化を回避
  • LSStreamFlush / Dispose で LocalStorage へ保存
  • IDBStreamFlushAsync / DisposeAsync で IndexedDB へ保存
  • async flush 中に別の write が行われた場合、古い flush が新しい dirty state を消さないよう write version を追跡
  • 複数 write が flush / dispose で順序通り永続化される回帰テストを追加
  • IndexedDB のテストは他PRに依存しない独立ファイルへ分離

同期 Dispose / Flush の扱い

IndexedDB の永続化は非同期処理です。dirty な IDBStream に対して同期 Flush / Dispose を呼ぶと、完了を待てずにデータを失う可能性があります。このPRでは黙って破棄せず例外を送出し、FlushAsync または DisposeAsync の利用を要求します。LocalStorage は同期 API のため、LSStream の同期 Flush / Dispose で保存できます。

影響範囲

  • 公開 API のシグネチャ変更なし
  • write ごとの永続化から、stream として一般的な flush / dispose 境界での永続化へ変更
  • IDBStream の利用側は、書き込み後に FlushAsync または DisposeAsync が必要
  • 保存される最終バイト列の形式は変更なし

検証

  • dotnet format を変更 C# ファイルへ実行
  • 統合差分で Rider / Unity コンパイル成功
  • WebGL Player テスト画面で All test(s) succeeded を確認
  • LocalStorage: 複数 write を flush / dispose した結果を検証
  • IndexedDB: 複数 WriteAsyncDisposeAsync した結果を再読み込みして検証

@kochounoyume kochounoyume self-assigned this Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant