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

あえてPHPでリアルタイム通信をやってみる

 あえてPHPでリアルタイム通信をやってみる

フロントエンド・PHPカンファレンス北海道2026
#frontend_phpcon_do #vaddy_room

Avatar for Miyamoto Naoyuki

Miyamoto Naoyuki

June 05, 2026

More Decks by Miyamoto Naoyuki

Other Decks in Technology

Transcript

  1. $ cat profile.service [Unit] Description=Self Introduction After=network.target [Profile] Name="Miyamoto Naoyuki"

    Twitter="@Msprzk" Affiliation="北海道情報大学2年" Interest="Network",”Security”,”WebRTC”
  2. 検証方法 - PHP / TypeScript / Go でWebSocket relayを実装 -

    動画を送信し、20のreceiverにrelayする - 送信は基本的にPlaywrightのheadless(GUI付きとあまり変わらない結果 だったので、全てheadlessで撮り直しました) - 各実装ごとに10回実行 - 実行順による偏りを避けるため、ランダムな順番で実行 - 各実行ごとにp95, p99, max latency, loss, append error を計測 - 比較値は主に10回の実行の median p95, p99 = 遅延分布の95%, 99%地点. 99%地点が悪いほど、まれに大きくつまっているということ
  3. 単一プロセスの場合 実装 loss append error 受信側p99 遅延 サーバ側 p99遅延 評価

    TS 0 0 15.05ms 3.00ms 成立 PHP 0 0 61.95ms 19.50ms 成立 Go 0 0 24.80ms 5.50ms 成立 ※ p99: 遅延分布の99%地点。数値は10回実行した中央値。 ※ 受信側 p99 遅延: 各receiverのp99を平均した値。
  4. PHP-FPM(風) 実装 モデル ready p50 ready p99 評価 php-process-pool FPM的worker

    pool 10112.00ms 20218.50ms 後続接続が待 たされる ts-native Node.js event loop 4.00ms 9.00ms ほぼ同時 go-native Go goroutine 4.00ms 14.00ms ほぼ同時
  5. 1. 接続を変える場所 - 長命接続をどの実行モデルで持つか - FPM風 worker poolでは、connectionがworkerを占有 2. 接続後に送る場所

    - 接続済みreceiverにどう配信するか - 遅いreceiverの影響を他receiverに波及させないか リアルタイム通信で詰まる場所は2つある
  6. 実装 送信設計 受信側p99 サーバー側p99 通常receiver p99 評価 php-ws 全receiverへ同 期write

    95.90ms 13.00ms 86.49ms 波及しやすい php-ws-queued receiverごとの write buffer 46.67ms 3.00ms 27.12ms 波及が減る
  7. - FPM風 worker poolの問題は、長命接続をどこで抱えるかという 実行モデルの問題 - Queued での問題は、接続後にどう送るかという送信設計の問題 つまり、PHPでリアルタイム通信をやるなら、 -

    FPM的な request/response モデルから外す - 常駐サーバー内で receiver ごとの queue / backpressure を設計する という2段階の設計が必要になる ここから言えること
  8. PHP Manual: FastCGI Process Manager (FPM) https://www.php.net/manual/en/install.fpm.php PHP Manual: FPM

    Configuration https://www.php.net/manual/en/install.fpm.configuratio n.php 参考