$30 off During Our Annual Pro Sale. View Details »

コロプラはなぜゲームアプリケーションで PHP を使い続けるのか

コロプラはなぜゲームアプリケーションで PHP を使い続けるのか

\積極的に技術発信を行なっております/

▽ Twitter/COLOPL_Tech
https://twitter.com/colopl_tech

▽ connpassページ
http://colopl.connpass.com

▽ COLOPL Tech Blog
http://blog.colopl.dev

COLOPL Inc.

July 27, 2023
Tweet

More Decks by COLOPL Inc.

Other Decks in Technology

Transcript

  1. サーバー基盤グループ PE チーム 工藤 剛
    コロプラは
    なぜゲームアプリケーションで
    PHP を使い続けるのか

    View Slide

  2. 2
    2017 年新卒として入社、運用タイトルのサーバーエンジニアを経て
    SRE チームを経て PE (Platform Engineering) チームへ
    主にミドルウェアの更新対応やアプリケーションの保守性向上などに
    取り組んでいる
    PHP おじさん
    氏名  :
    部署名 :
    自己紹介
    工藤 剛
    技術基盤本部 第 3 バックエンドエンジニア部
    サーバー基盤グループ PE チーム

    View Slide

  3. コロプラにおけるサーバーサイド構成図
    3
    引用: 大規模ゲームインフラとしての Kubernetes とノーメンテナンス運用
    https://speakerdeck.com/toversus/da-gui-mo-kemuinhuratositefalse-kubernetes-tofalsementenansuyun-yong

    View Slide

  4. 4
    コロプラにおける Server たち
    ● API Server
    ○ ステートレスに行える処理
    ■ プレイ開始・終了
    ■ データの取得・生成・永続化
    ○ を採用
    ● Game (Real Time) Server
    ○ ステートフルな処理
    ■ PvP, PvE におけるリレー通信
    ■ Live Streaming における一対多・多対多通信
    ○ を主に使用

    View Slide

  5. なぜ Web 用の言語である PHP をゲームに使うのか?
    5
    よくある疑問

    View Slide

  6. なぜ Web 用の言語である PHP をゲームに使うのか?
    スケールが容易でステートレスな
    サーバーサイド実装に最適な言語だから
    6
    よくある疑問

    View Slide

  7. PHP は求められる要件をほとんど満たしている
    ● スクラップアンドビルドのサイクルを高速化できること
    ○ 高速なイテレーションこそが高品質な製品を産むという考え
    ● ステートレスであること
    ○ ステートを持たず、並列化することで容易にスケールアウトできること
    ● 負荷が予測可能であること
    ○ ガベージコレクションなどがほぼ発生せず、常に安定したパフォーマンスで
    動作できること
    ● パフォーマンスが良いこと
    ○ 実行効率に優れ、莫大なリクエストを正しく処理できること
    ● 言語レベルの実装を理解できること
    ○ 何かあれば言語の実装を確認し、問題の原因追求ができること
    7
    コロプラで求められるアーキテクチャ

    View Slide

  8. コードを書き換えて保存するだけで即時実行することができる
    コンパイラ型・トランスパイラ型の言語ではどうしても待ちが発生する
    (インタプリタ型でも機械語へのコンパイルは発生するが、オンデマンドなので待ち時間は短い)
    8
    スクラップアンドビルドの高速化




    Java

    (bytecode)

    View Slide

  9. とはいいつつも、現状に見合わない部分も...
    ● K8s 環境下では結局コンテナイメージのビルド待ちが発生する
    ● 他言語のコンパイルにかかる時間が大幅に高速化されてきている
    ○ AOT で直接バイナリコードを吐く言語 (Go 等) が優秀
    ● opcache.validate_timestamps=0 環境下では単に書き換えるだけではダメ
    正直なところ、開発サイクルの高速化というメリットは
    だいぶ弱くなってきている印象...
    9
    スクラップアンドビルドの高速化

    View Slide

  10. Request1 End
    一般的な SAPI*1 (apache2handler, fpm, cgi 等) ではリクエストごとにステートが破棄される
    前回実行した結果に依存した処理は PHP だけでは原理的に実装できない*2
    ため、
    基本的に実装がステートレスになりスケーラビリティを担保しやすい
    10
    ステートレス性
    Zend Engine + Extension
    Request1 Start
    Free
    Zend Engine + Extension Request1 Working Memory Free
    Request2 Start
    Zend Engine + Extension Free
    Request2 End
    Zend Engine + Extension Request2 Working Memory Free
    *1: Server Side API: PHP の実行形態 *2: Extension の導入や常駐化、サードパーティ SAPI などを行えば可能

    View Slide

  11. 負荷見積もりにおける理想の姿は "常に一定のスループットを維持" してくれる形
    ただし、様々な理由からそのようなことにはならない
    ● API ごとのリソース特性の違い (I/O bound, CPU bound, etc…)
    ● キャッシュされていないデータへのアクセスによる待機時間
    ● 実行環境のハードウェアに起因するスループットの変化
    "詰まり" (スパイク) が発生すると負荷が一部に偏りユーザー体験に影響を
    及ぼす恐れがあるため、ワーストケースに合わせてサービス影響が出ないような
    構成を取る必要が生じる
    (≒ コスト増加)
    11
    負荷の予測可能性

    View Slide

  12. Node.js アプリケーションにて GC (Full GC) でスパイクが発生している図
    (縦軸はレイテンシ)
    12
    負荷の予測可能性

    View Slide

  13. PHP は他言語に比べ、比較的負荷予測が容易
    ● スパイク (詰まり) が起きにくい
    ○ "特定の状況下でのみ発生するパフォーマンス劣化" が原理的に起きにくい
    ■ パフォーマンスに大きな影響を与える循環参照 GC をほぼ考慮しなくて良い
    ■ "リクエストが詰まる" ようなことが少なく、 DB など特定のコンポーネントへ
    突然負荷が集中する状況が起きにくい
    ● リクエストを受けてから実行までの時間にばらつきが少ない
    ○ 仮想マシンのフットプリントが小さく、リクエストを処理可能になるまでの時間が短い
    ● パフォーマンスチューニングが容易
    ○ 負荷試験結果からある程度適切な割当リソース量を見積もりやすい
    13
    負荷の予測可能性

    View Slide

  14. PHP はインタプリタの中でもかなりパフォーマンスの良い言語
    Node.js (V8) には敵わないものの、 JIT を有効にすれば匹敵する性能
    とはいえここまで CPU バウンドな処理は実際のワークロードにはほぼない
    14
    良好なパフォーマンス
    "一般的なコード" でテストするため
    実装コードは ChatGPT (GPT-4) で生成
    コードの手直しや最適化は一切なし
    40 x 80 で 8192 回走査

    View Slide

  15. OPcache 拡張機能を利用することで実行効率を大幅に向上可能
    ● コードパス解析による最適化
    ● OPcode コンパイル結果の共有メモリ (shm) へのキャッシュ
    ● 定数配列のメモリへのキャッシュ (PHP 7.0 以降)
    ○ 詳細は hnw さんの記事が詳しいです
    https://hnw.hatenablog.com/entry/2020/08/12/212433
    ● preload (実行前事前ロード) (PHP 7.4 以降)
    ● Just-in-Time Compiler (PHP 8.0 以降)
    ○ 実際のワークロードで 10% 程度効率改善を確認
    15
    良好なパフォーマンス
    FPM PM
    OPcache shm
    worker worker worker
    script script

    View Slide

  16. APCu 拡張を利用することで、 OPcache 同様 shm 領域を簡易的な KVS として
    利用することができる
    実際にマスタデータキャッシュ用途で利用しており
    パフォーマンスの改善とデータベースの負荷低減に役立っている
    store / fetch 時に serialize / unserialize コストがかかるので注意
    16
    良好なパフォーマンス
    FPM PM
    APCu shm
    worker worker worker
    DB

    View Slide

  17. PHP 自体は C 言語で実装されており、乱雑とはしているが
    コードの雰囲気を読み取る程度は (HHVM 等に比べて) 比較的容易
    ビルドツールチェーンやデバッグ関連機能も整備が行き届いており
    gdb や lldb を使ったデバッグや Valgrind, LLVM Sanitizer を使った
    メモリチェックなども快適で、良い意味で枯れている
    17
    言語実装の明瞭性

    View Slide

  18. "何かあった時に自前でなんとかできる" 安心感が PHP にはある!
    サイボウズさんではパッチを当ててビルドした PHP を使用 (!)
    ● https://speakerdeck.com/akamah/20nian-mononoju-da-regasipurodakut
    owo-php-8-dot-0niatupudetositaji-nodui-ce-tode-raretazhi-jian
    コロプラでも PHP Extension を作成・保守しています (OSS)
    ● https://blog.colopl.dev/entry/2023/07/06/110000
    ○ 奇しくもサイボウズさんとほぼ同じものを作っていました
    18
    言語実装の透明性

    View Slide

  19. PHP はステートレスなサーバーサイド言語として未だ有望!
    もちろん解決したい問題がないわけではない
    ● より実行効率を追求したい
    ○ リクエスト単位での初期化を部分的にやめる (RoadRunner, Swoole, FrankenPHP,...)
    ● コンテナ環境での使い勝手を改善したい
    ○ 現状 HTTP サーバーが別途必要
    ● もっと型安全にコードを書きたい
    ● etc...
    次の PHP Innovator は君だ!!!
    19
    まとめ

    View Slide