14 ポイント 投稿者 GN⁺ 2024-11-08 | 3件のコメント | WhatsAppで共有
  • recallは数百社に会議用ボットを提供するサービスで、AWS上で大規模なインフラを運用している
  • コスト効率の高いサービスのために、ハードウェア性能を最大限活用しようとしていた
  • 過去数年間、クラウドプロバイダーのGPU可用性が不安定だったため、動画処理はGPUではなくCPUで実行していた
  • ヘッドレスChromiumを使うボットをプロファイリングした結果、CPU時間の大半は動画処理(エンコード/デコード)ではなく、メモリコピー関数 __memmove_avx_unaligned_erms__memcpy_avx_unaligned_erms に費やされていた
    • memmovememcpy はC標準ライブラリ(glibc)にあるメモリブロックコピー関数
    • memmove は重複する範囲のメモリコピーに関するいくつかの例外ケースを処理するが、両方とも「メモリコピー」関数に分類できる
    • avx_unaligned_erms という接尾辞は、Advanced Vector Extensions(AVX)をサポートするシステム向けに最適化され、未整列メモリアクセスにも最適化されていることを意味する
    • erms は Enhanced REP MOVSB/STOSB の略で、最新のIntelプロセッサで高速なメモリ移動を行うための最適化。「特定プロセッサ向けのより高速な実装」と考えられる
  • プロファイリングの結果、これらの関数を最も多く呼び出していたのはデータを受信するPython WebSocketクライアントだった
    • その次に多かったのは、データを送信するChromiumのWebSocket実装だった

WebSocketの問題点

  • 生の動画データをChromiumのJS環境からエンコーダへ送るために、ローカルWebSocketサーバーを使っていた
  • 生の1080p 30fps動画ストリームは、毎秒93MBを超える高い帯域幅を要求する
  • WebSocketの利用が大きな計算コストを招いており、主な原因は断片化(fragmentation)とマスキング(masking)だった
    • 断片化: ChromiumのWebSocket実装は131KBを超えるメッセージを複数フレームに断片化する。3MBを超える生の動画フレームは24個以上の個別フレームに分割されて送信される
    • マスキング: セキュリティ上の理由から、WebSocketはクライアントからサーバーへ送信されるすべてのフレームをマスクする。毎秒100MBを超える大容量データでは無視できないオーバーヘッドになる

代替案の模索

  • ブラウザAPIだけではWebSocketよりはるかに高性能なものを実装するのが難しかったため、Chromiumをフォークしてカスタム機能を実装することにした
  • 3つの代替案を検討した: raw TCP/IP、Unix Domain Socket、Shared Memory
    • TCP/IP: WebSocketの断片化/マスキング問題は回避できるが、最大パケットサイズが小さいため依然として断片化の問題がある。カーネル空間へのコピーオーバーヘッドもある
    • Unix Domain Socket: ネットワークスタックを完全に迂回できるが、ユーザー空間とカーネル空間の間でデータコピーが必要
    • Shared Memory: 複数プロセスが同時にアクセスできるメモリ。途中でコピーせずにChromiumが共有メモリへ直接書き込み、エンコーダがそのまま読み取れる

共有メモリベースの転送実装

  • 共有メモリにデータを連続して読み書きするため、リングバッファ形式で実装した
  • 要件: lock-free、マルチプロデューサ/シングルコンシューマ、可変フレームサイズ、ゼロコピー読み取り、サンドボックス親和性、低遅延シグナリング
  • 既存のリングバッファ実装を評価したが、要件をすべて満たすものがなかったため自前で実装することにした
  • ゼロコピー読み取りをサポートするため、ポインタを write、peek、read の3つに分けた
  • スレッド安全性のためにアトミック演算を使い、新しいデータの発生や空き領域の確保を通知するために named semaphore を使用した
  • 共有メモリベースのリングバッファ実装とその他の最適化により、ボットのCPU使用量を最大50%削減できた。結果としてAWS費用を年間100万ドル以上削減した。

3件のコメント

 
GN⁺ 2024-11-08
Hacker Newsの意見
  • あるスタートアップが「十分に良い」近道を選び、後で最適化するという典型的な話だという意見。

    • ある会社では CPU 使用率の高い VM クラスターがあり、これを最適化するためにプロファイラを使った。
    • 古いデータを削除し、クエリにフィルターを追加して CPU 使用率を下げた。
  • 生の動画データの帯域幅の大きさに驚いたという意見がある。

    • WebSockets の設計判断を批判し、CPU 使用量の問題を予見できなかったとしている。
  • AWS の問題ではなく、CPU サイクルを浪費した問題だという意見がある。

    • WebSockets はデータ転送や API ゲートウェイのコストに関係している。
  • TCP/IP ネットワークの MTU と MSS が動画フレームサイズに比べて小さい点を指摘している。

    • 技術的知識の不足を指摘し、開発者を雇う必要があると主張している。
  • Chromium の Mojo を使えば、プラットフォームごとのコードを気にする必要がないという意見がある。

    • カスタムのリングバッファ実装も悪くないと考えている。
  • 問題はネットワークではなく、動画コーデックへの理解不足だという意見がある。

    • RDP のような動画ストリーミングプロトコルを使わない理由が理解できないとしている。
  • 透明性を称賛し、製品価格についての透明性も望むとしている。

  • WebSocket プロトコルのマスキングは中間者の問題を解決しようとする試みだと説明している。

    • 関連する RFC を読んでみる価値があるとしている。
  • 動画データを圧縮せずに転送する方式はおかしいと指摘している。

    • 圧縮済みストリームを送らない理由が理解できないとしている。
  • 生の動画を WebSocket で送る初期アプローチに驚いたとしている。

    • 非効率性が製品開発の妨げにならなかったとしている。
    • データ量を考慮しないアプローチは理解できないとしている。
 
ahwjdekf 2024-11-09
  • 製品開発時に、性能についての考慮はまったくなかったのだと思う。
  • この問題は結局、大量データをどうIPCするかという問題に帰着する。
  • 違いは一般的なIPCではなく、ChromeブラウザとIPCするという点であり、
  • Chromeブラウザ内部の方式はそれほど簡単ではないだろうが、オープンになっているので修正は可能。
  • となると結局、IPCの選択の問題だ。

最初から開発を間違えていたんだな…

 
ahwjdekf 2024-11-09

「生の動画をWebSocketで送信するという初期アプローチは驚きだ」とのこと。これには共感する。