Cygamesを支えるPHPと、その高速化の取り組み

510ec964f5d26c2724c883fd7b671e3d?s=47 Cygames
November 08, 2016

 Cygamesを支えるPHPと、その高速化の取り組み

2016/11/03 PHPカンファレンス 2016

510ec964f5d26c2724c883fd7b671e3d?s=128

Cygames

November 08, 2016
Tweet

Transcript

  1. None
  2. ©  Cygames,  Inc. 今回お話したいこと Cygamesのアプリはピーク時には秒間5万アク セス100万クエリを捌く必要があります サーバーサイドは、最⾼高のコンテンツを開発し、 それを⾼高速かつ安定的に提供することを⽬目指して います。 今回はそのサーバー構成/技術や、どのような価

    値観で開発しているかと、⾼高速化の取り組みを紹 介します!
  3. ©  Cygames,  Inc. 今回お話したいこと • 前半 • Cygamesのサーバー構成/技術スタック • コンテンツ開発に対してのマインドセット

    • 負荷分散/⾼高速化/リリースでの取り組み • 後半 • ⾼高速化のためZephir導⼊入検討 • Zephirの概要と導⼊入 • 運⽤用してみてとこれから
  4. ©  Cygames,  Inc. ⾃自⼰己紹介 • ⼩小笠笠原空宙(たかひろ) • サーバーサイドエンジニーア • ほぼPHP

    • ちょっとperl • 2014年年7⽉月 Cygames join • その前はモバイルサイト/ソーシャルゲーム開発
  5. ©  Cygames,  Inc. ©  Cygames,  Inc. 5 ちょっと紹介

  6. ©  Cygames,  Inc.

  7. ©  Cygames,  Inc.

  8. ©  Cygames,  Inc.

  9. ©  Cygames,  Inc. ©  Cygames,  Inc.

  10. ©  Cygames,  Inc. ©  Cygames,  Inc. MySQLに変わるDB 「 CySQL 」を開発中!

    •シャドーバースポータルで ⼀一部稼働済み
  11. ©  Cygames,  Inc.

  12. ©  Cygames,  Inc. 5000万DL 300万⼈人プレイ/daily

  13. ©  Cygames,  Inc. とあるアプリの現状 • ⽉月間300億PV • ピーク時、秒間5万アクセス • ピーク時、秒間100万クエリ

    • 1⽇日のDBのトランザクションデータ増加量量 • 1〜~2TB • 1⽇日のログデータ増加量量 • 60GB〜~
  14. ©  Cygames,  Inc. Cygamesを⽀支えるサーバーサイド • サーバー構成/技術スタック • 何を、どのように利利⽤用しているのか • 開発スタイル/マインドセット

    • どのような価値観で開発しているか • 負荷分散/⾼高速化/リリースでの取り組み • 開発~∼運⽤用までの取り組み • 今/これからの取り組み • 今後どう前進しようとしているか
  15. ©  Cygames,  Inc. ©  Cygames,  Inc. 15 とあるサーバー構成例例

  16. ©  Cygames,  Inc. とあるサーバー構成例例(⼤大雑把な) Batch PHP Node.js PHP-‐‑‒FPM Nginx MySQL

    Memcached redis
  17. ©  Cygames,  Inc. とあるサーバー構成例例(⼤大雑把な) Batch PHP Node.js PHP-‐‑‒FPM Nginx MySQL

    Memcached redis
  18. ©  Cygames,  Inc. とあるサーバー構成例例(⼤大雑把な) Batch PHP Node.js PHP-‐‑‒FPM Nginx MySQL

    Memcached redis
  19. ©  Cygames,  Inc. とあるサーバー構成例例(⼤大雑把な) Batch PHP Node.js PHP-‐‑‒FPM Nginx MySQL

    Memcached redis
  20. ©  Cygames,  Inc. とあるサーバー構成例例(⼤大雑把な) Batch PHP Node.js PHP-‐‑‒FPM Nginx MySQL

    Memcached redis
  21. ©  Cygames,  Inc. とあるサーバー構成例例(⼤大雑把な) Batch PHP Node.js PHP-‐‑‒FPM Nginx MySQL

    Memcached redis
  22. ©  Cygames,  Inc. とあるサーバー構成例例(⼤大雑把な) Batch PHP Node.js PHP-‐‑‒FPM Nginx MySQL

    Memcached redis
  23. ©  Cygames,  Inc. とあるアプリの周辺技術

  24. ©  Cygames,  Inc. とあるアプリの周辺技術 Ansible Vagrant Munin Mackerel Jenkins New

     Relic Google  BigQuery Fluentd Elasticsearch Kibana
  25. ©  Cygames,  Inc. ©  Cygames,  Inc. 25 開発スタイル マインドセット

  26. ©  Cygames,  Inc. ©  Cygames,  Inc. 26 ⾯面⽩白くなければ 意味がない

  27. ©  Cygames,  Inc. ⾯面⽩白くなければ意味がない • ⾯面⽩白さにゴールはない…

  28. ©  Cygames,  Inc. ⾯面⽩白くなければ意味がない • ⾯面⽩白さにゴールはない… • 素早くトライ&エラーを繰り返す • 素早く微調整を繰り返す

    • それが⾏行行いやすい実装 • ⾯面⽩白くなければばっさり捨てることも厭わない
  29. ©  Cygames,  Inc. ©  Cygames,  Inc. 29 CS最優先

  30. ©  Cygames,  Inc. CS(カスタマーサポート)最優先 • お客様からの問い合わせには即対応 • 即対応できるようなログの設計 • ログの可視化ツールの構築

    • 本番環境のデータを複製し、実機で動きを確認 できる検証環境 • 確証を持って対応できるように
  31. ©  Cygames,  Inc. ©  Cygames,  Inc. 31 当たり前のことを 当たり前にやる

  32. ©  Cygames,  Inc. 当たり前のことを当たり前にやる • ⼩小さな差がピーク時に⼤大きな差に • 不不必要な処理理は書かない • 不不必要なデータは取得しない

    • 適切切なリファクタリング • 運⽤用し易易い実装、拡張しやすい実装 • ⽇日々の積み重ねが、 良良くも悪くもピーク時に顕在化する
  33. ©  Cygames,  Inc. 当たり前のことを当たり前にやる • 当たり前のレベルがスピードにつながる • ほぼ毎⽇日複数回デプロイ • ほぼ常にイベント開催

    • 新機能追加、機能改善、etc • PJに関わる⼈人間も多くなる • 当たり前のことを増やし、積み上げることで チームのレベルを上げていく
  34. ©  Cygames,  Inc. ©  Cygames,  Inc. 34 負荷分散/⾼高速化/ リリース での取り組み

  35. ©  Cygames,  Inc. 秒間5万アクセス 秒間5万アクセスのアクセスを 捌くため負荷分散/処理理の⾼高速化は サーバーサイドの最重要課題!

  36. ©  Cygames,  Inc. 負荷分散/スケールアウトの取り組み • DBは⽔水平、垂直分割 • キャッシュはTwemproxyで分散 • Node.jsはNginxでバランシング

    • 各種ログは⾮非同期で保存 • バッチ処理理できるものはバッチ処理理へ • 分散/スケールアウトできるように • できるだけキャッシュ • 同期処理理は必要最低限に
  37. ©  Cygames,  Inc. ©  Cygames,  Inc. 37 ⾼高速化の取り組み

  38. ©  Cygames,  Inc. プロファイリングの取り組み • 「推測するな、計測せよ」 • New  relicで解析 •

    以前はxhprofなど • 重いクエリ、最適化できる処理理などを地道に対応 • FW側の不不要な処理理なども最適化 • 4.5秒以上かかったリクエストを⽇日次で集計、通知 • 検知 ⇔  最適化の地道な対応 イベント開始><; 負荷対策リリース\(^o^)/ レスポンスタイム推移
  39. ©  Cygames,  Inc. DB関連での取り組み • ボトルネックの多くはDB関連 • トランザクション中の処理理は最⼩小限に • まとめられるクエリはまとめる

    • indexはカーディナリティが⾼高い順に • ⽇日次で開発環境で実⾏行行された全クエリをexplain • 問題のありそうなクエリは通知
  40. ©  Cygames,  Inc. DB関連での取り組み • 本番DBのGeneral_̲Log,Slow_̲Queryも解析

  41. ©  Cygames,  Inc. DB関連での取り組み • 本番DBのGeneral_̲Log,Slow_̲Queryも解析 • テーブル単位でサマリー • ロック、処理理件数など確認できる

  42. ©  Cygames,  Inc. DB関連での取り組み • 本番DBのGeneral_̲Log,Slow_̲Queryも解析 • 実際に実⾏行行されたクエリを⼀一覧 • 渡されたパラメータ等確認

    • 運⽤用の過程でレコードの偏りなどで不不適切切なindex が選択されることも
  43. ©  Cygames,  Inc. DB関連での取り組み • 本番DBのGeneral_̲Log,Slow_̲Queryも解析 • 対象クエリのexplain表⽰示 • index,type,partition

    など確認
  44. ©  Cygames,  Inc. DB関連での取り組み • とにかくデータがもりもり増えていく • トランザクションデータは毎⽇日1~∼2TB単位で増加 • CS/分析⽤用途の⾏行行動ログも毎⽇日60GB〜~で増加

    • 必要なくなったデータは順次パージしないと ディスク容量量を圧迫してしまう
  45. ©  Cygames,  Inc. DB関連での取り組み • 必要なくなったデータは順次パージ • イベント単位でテーブル作成、終了了後にdrop • パーティション単位で毎⽇日drop&add

    • 不不要なテーブルは週次でアラートを通知 • 常に必要なデータのみを保持するように
  46. ©  Cygames,  Inc. DB関連での取り組み • 数⼗十GBのテーブルを安全にdropする • データファイルが⼤大きいとファイル削除時、 io_̲waitで数秒間ではあるがレスポンス劣劣化 i.

    drop対象のデータファイルにhard  link貼る ii. drop  table実⾏行行 iii. hard  linkしたファイルのサイズを切切り詰めた後 に、remove(linuxのtruncateコマンド) • ゆるやかに削除することで数百テーブル、合計数百 GBのテーブル削除もレスポンス劣劣化なく実⾏行行
  47. ©  Cygames,  Inc. リリース時の取り組み • リリース前には職種/チーム問わずレビュー • 全スタッフ ≒  ゲームユーザ

    • プランナー/エンジニア/デザイナ/バックオフィス • ⾯面⽩白いと確信が持てるまでブラッシュアップ • リリース前には実際に運⽤用テスト • 各種更更新作業などの通常運⽤用リハーサル • 緊急デプロイなどの障害対応フローなども確認
  48. ©  Cygames,  Inc. ©  Cygames,  Inc. 48 今/これからの取り組み

  49. ©  Cygames,  Inc. 今/これからの取り組み • PHP7対応 • FWのcoreを拡張させている箇所の対応 • 各種extensionの対応状況の調査

    • 品質と⽣生産性の向上、仕組みづくり • ゲーム特有の問題を検知できる仕組み • ユニット/E2Eテストだけではない何か • Zephirによる⾼高速化/共通化 • この後詳しく・・・
  50. ©  Cygames,  Inc. ⼀一旦まとめ • Cygamesサーバーサイドは、最⾼高のコンテン ツを開発し、それを⾼高速/安定的な提供を⽬目標 としています • ⽇日々、トライ&エラー/実装⇔計測を地道に繰

    り返し実績を積み上げ、上記の実現を⽬目指して います!
  51. ©  Cygames,  Inc. ©  Cygames,  Inc. Zephirやってみた ⼩小笠笠原 空宙

  52. ©  Cygames,  Inc. 経緯 • レスポンスの⾼高速化は最優先事項の1つ • クエリ/処理理最適化もある程度度やった感 • (まだまだ最適化できることはあるけど…)

    • 違う⾓角度度からの最適化を⾏行行いたい
  53. ©  Cygames,  Inc. Zephir検討への経緯 • レスポンスの⾼高速化は最優先事項の1つ • クエリ/処理理最適化もある程度度やった感 • (まだまだ最適化できることはあるけど…)

    • 違う⾓角度度からの最適化を⾏行行いたい ミドルウェアのバージョン 上げようぜ!
  54. ©  Cygames,  Inc. Zephir検討への経緯 • レスポンスの⾼高速化は最優先事項の1つ • クエリ/処理理最適化もある程度度やった感 • (まだまだ最適化できることはあるけど…)

    • 違う⾓角度度からの最適化を⾏行行いたい ミドルウェアのバージョン 上げようぜ! フレームワーク変えようぜ!
  55. ©  Cygames,  Inc. Zephir検討への経緯 • レスポンスの⾼高速化は最優先事項の1つ • クエリ/処理理最適化もある程度度やった感 • (まだまだ最適化できることはあるけど…)

    • 違う⾓角度度からの最適化を⾏行行いたい ミドルウェアのバージョン 上げようぜ! フレームワーク変えようぜ! ⾔言語変えようぜ!
  56. ©  Cygames,  Inc. Zephir検討への経緯 • レスポンスの⾼高速化は最優先事項の1つ • クエリ/処理理最適化もある程度度やった感 • (まだまだ最適化できることはあるけど…)

    • 違う⾓角度度からの最適化を⾏行行いたい ミドルウェアのバージョン 上げようぜ! フレームワーク変えようぜ! ⾔言語変えようぜ! ⾯面⽩白くなければ意味がない エンジニア的にはやってみたいんだがしかし・・・
  57. ©  Cygames,  Inc. Zephir検討への経緯 • レスポンスの⾼高速化は最優先事項の1つ • クエリ/処理理最適化もある程度度やった感 • (まだまだ最適化できることはあるけど…)

    • 違う⾓角度度からの最適化を⾏行行いたい ミドルウェアのバージョン 上げようぜ! フレームワーク変えようぜ! ⾔言語変えようぜ! ⾯面⽩白くなければ意味がない エンジニア的にはやってみたいんだがしかし・・・ Zephirっていうのが あるらしいぞい
  58. ©  Cygames,  Inc. Zephirとは • PHPerでも簡単にextensionが書ける⾔言語 • PHPのような記述でextensionが作成できる • if⽂文の書式が違う

    • 変数に$使わない • 変数上書き時は、let  を使う • 静的/動的型⾔言語 • メモリ管理理等が必要ない • ⾼高速FW PhalconはZephirで実装
  59. ©  Cygames,  Inc. Zephirについて • Hello  World namespace  Utils; class

     Hello { //say  func public  static  function  say() { echo  "Hello  World!"; } } <?php Utils¥Hello::say();    //  prints  Hello  World! $zephir build
  60. ©  Cygames,  Inc. Extensionが⽣生成/実⾏行行までのフロー 1. Zephirのスケルトンを作成 $zephir init utils utils

    ├──  ext //Zephirのcore,⽣生成されるextensionなどが配置される │ └──  utils //ここに.zepファイルを作成していく
  61. ©  Cygames,  Inc. Extensionが⽣生成/実⾏行行までのフロー 2.Zephirのファイルを作成 $vim  utils/hello.zep namespace  Utils; class

     Hello { public  static  function  say() { echo  "Hello  World!"; } }
  62. ©  Cygames,  Inc. Extensionが⽣生成/実⾏行行までのフロー 3.Zephirでextension⽣生成→compile • ZephirがPHPで.zepファイルを解析 • C⾔言語のextensionファイル群⽣生成 •

    gccでコンパイル、.soファイルをext_̲dirにコピー $zephir build Compiling... Installing... Extension  installed! Don't  forget  to  restart  your  web  server hello.zep C⾔言語 utils ext ファイル群 utils.so PHP gcc
  63. ©  Cygames,  Inc. どんなソースが⽣生成される? • Zephirでフィボナッチ数列列 • 定義通り再帰でやってみる class  Fib

    { public  function  calc(int n)  -‐‑‒>  int { if  n  <  2  { return  n; } return  self::calc(n  -‐‑‒ 1)  +  self::calc(n  -‐‑‒ 2); } }
  64. ©  Cygames,  Inc. どんなソースが⽣生成される? PHP_̲METHOD(Utils_̲Fib,  calc)  { zval *n_̲param =

     NULL,  *_̲0  =  NULL,  *_̲1  =  NULL,  *_̲2  =  NULL; int n,  ZEPHIR_̲LAST_̲CALL_̲STATUS; ZEPHIR_̲MM_̲GROW(); zephir_̲fetch_̲params(1,  1,  0,  &n_̲param); n  =  zephir_̲get_̲intval(n_̲param); if  (n  <  2)  { RETURN_̲MM_̲LONG(n);} ZEPHIR_̲INIT_̲VAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 1)); ZEPHIR_̲CALL_̲SELF(&_̲0,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); ZEPHIR_̲INIT_̲NVAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 2)); ZEPHIR_̲CALL_̲SELF(&_̲2,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); zephir_̲add_̲function(return_̲value,  _̲0,  _̲2); RETURN_̲MM(); }
  65. ©  Cygames,  Inc. どんなソースが⽣生成される? PHP_̲METHOD(Utils_̲Fib,  calc)  { zval *n_̲param =

     NULL,  *_̲0  =  NULL,  *_̲1  =  NULL,  *_̲2  =  NULL; int n,  ZEPHIR_̲LAST_̲CALL_̲STATUS; ZEPHIR_̲MM_̲GROW(); zephir_̲fetch_̲params(1,  1,  0,  &n_̲param); n  =  zephir_̲get_̲intval(n_̲param); if  (n  <  2)  { RETURN_̲MM_̲LONG(n);} ZEPHIR_̲INIT_̲VAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 1)); ZEPHIR_̲CALL_̲SELF(&_̲0,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); ZEPHIR_̲INIT_̲NVAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 2)); ZEPHIR_̲CALL_̲SELF(&_̲2,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); zephir_̲add_̲function(return_̲value,  _̲0,  _̲2); RETURN_̲MM(); } int型で⽐比較を ⾏行行っている
  66. ©  Cygames,  Inc. どんなソースが⽣生成される? PHP_̲METHOD(Utils_̲Fib,  calc)  { zval *n_̲param =

     NULL,  *_̲0  =  NULL,  *_̲1  =  NULL,  *_̲2  =  NULL; int n,  ZEPHIR_̲LAST_̲CALL_̲STATUS; ZEPHIR_̲MM_̲GROW(); zephir_̲fetch_̲params(1,  1,  0,  &n_̲param); n  =  zephir_̲get_̲intval(n_̲param); if  (n  <  2)  { RETURN_̲MM_̲LONG(n);} ZEPHIR_̲INIT_̲VAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 1)); ZEPHIR_̲CALL_̲SELF(&_̲0,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); ZEPHIR_̲INIT_̲NVAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 2)); ZEPHIR_̲CALL_̲SELF(&_̲2,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); zephir_̲add_̲function(return_̲value,  _̲0,  _̲2); RETURN_̲MM(); } intではなく、 ZVALで値の やり取りをしている
  67. ©  Cygames,  Inc. どんなソースが⽣生成される? PHP_̲METHOD(Utils_̲Fib,  calc)  { zval *n_̲param =

     NULL,  *_̲0  =  NULL,  *_̲1  =  NULL,  *_̲2  =  NULL; int n,  ZEPHIR_̲LAST_̲CALL_̲STATUS; ZEPHIR_̲MM_̲GROW(); zephir_̲fetch_̲params(1,  1,  0,  &n_̲param); n  =  zephir_̲get_̲intval(n_̲param); if  (n  <  2)  { RETURN_̲MM_̲LONG(n);} ZEPHIR_̲INIT_̲VAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 1)); ZEPHIR_̲CALL_̲SELF(&_̲0,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); ZEPHIR_̲INIT_̲NVAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 2)); ZEPHIR_̲CALL_̲SELF(&_̲2,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); zephir_̲add_̲function(return_̲value,  _̲0,  _̲2); RETURN_̲MM(); } 再帰部分の 関数コール
  68. ©  Cygames,  Inc. どんなソースが⽣生成される? PHP_̲METHOD(Utils_̲Fib,  calc)  { zval *n_̲param =

     NULL,  *_̲0  =  NULL,  *_̲1  =  NULL,  *_̲2  =  NULL; int n,  ZEPHIR_̲LAST_̲CALL_̲STATUS; ZEPHIR_̲MM_̲GROW(); zephir_̲fetch_̲params(1,  1,  0,  &n_̲param); n  =  zephir_̲get_̲intval(n_̲param); if  (n  <  2)  { RETURN_̲MM_̲LONG(n);} ZEPHIR_̲INIT_̲VAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 1)); ZEPHIR_̲CALL_̲SELF(&_̲0,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); ZEPHIR_̲INIT_̲NVAR(_̲1); ZVAL_̲LONG(_̲1,  (n  -‐‑‒ 2)); ZEPHIR_̲CALL_̲SELF(&_̲2,  "calc",  NULL,  0,  _̲1); zephir_̲check_̲call_̲status(); zephir_̲add_̲function(return_̲value,  _̲0,  _̲2); RETURN_̲MM(); } ZVALなので intの⾜足し算も関数 コールになっている
  69. ©  Cygames,  Inc. Zephirでフィボナッチ数列列 • ZVALでの値のやりとり、関数コールもほぼ同 じようなのでそこまで⼤大きな差はでなかった • が、ほぼソース変えず⾼高速化 0

    0.5 1 1.5 2 2.5 3 3.5 4 4.5 PHP Zephir 90%程度度に [s]
  70. ©  Cygames,  Inc. ©  Cygames,  Inc. 70 もう少し実⽤用的なもの

  71. ©  Cygames,  Inc. Zephirでログ出⼒力力 • fwrite()でtsv形式でファイル出⼒力力 $fp =  fopen($file,  "a");

    fwrite($fp,  implode("¥t",  $msg_̲arr).PHP_̲EOL); fclose($fp); public  function  write(string  file,  array  msg_̲arr) { var fp =  fopen(file,  "a"); fwrite(fp,  implode("¥t",  msg_̲arr).PHP_̲EOL); fclose(fp); }
  72. ©  Cygames,  Inc. Zephirでログ出⼒力力 • fwrite()でtsv形式でファイル出⼒力力 • 単純な関数コールなので差は出にくい 0 10

    20 30 40 50 60 PHP Zephir ほぼ変わらず [ms]
  73. ©  Cygames,  Inc. ZephirでNGワードチェック • NGワード配列列をループさせてstrpos()で検索索 • NGワードは50語 public  $ng_̲list=

     [“ダメな⾔言葉葉”,“いけない⾔言葉葉”,“やばい⾔言葉葉",…]; public  function  check($str) { foreach ($this-‐‑‒>ng_̲list as  $key  =>  $value)  { if  (strpos($str,  $value)  !==  false)  { $is_̲ng =  true; //break;  ⽐比較のためbreakはしない } } }
  74. ©  Cygames,  Inc. ZephirでNGワードチェック • NGワード配列列をループさせてstrpos()で検索索 • 配列列が⼤大きくなるほど改善あり • strpos()はZephir側で⾼高速化されている

    0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 PHP Zephir 約20%程度度に!! [ms]
  75. ©  Cygames,  Inc. ⼀一旦ここまでわかったこと • PHPとの互換性のためZVALでの計算など、 実質PHPがやっていることと同様の事を⾏行行って いる様⼦子。C⾔言語的に最適化の余地はある • 配列列処理理などループ処理理などは速くなる

    • Zephirで標準関数のいくつか⾼高速化されている • PHPのコードをほぼ変えずに、Zephirの構⽂文 規則に整えればextension化ができる • 引数の型などはチェックは確実に⾏行行う • PHPだとwarningでもFATAL  ERRORになる
  76. ©  Cygames,  Inc. 改めてZephir/extension化すること • Pros • ⾼高速化できる • PJ/FWなど関係なく利利⽤用可能

    • 特定箇所のみに適応できる • PHPに戻すことも可能 • Cons • デプロイフローが増える • 修正がしにくい
  77. ©  Cygames,  Inc. 導⼊入箇所例例 • コード修正がほぼない共通処理理 • ループを多⽤用する箇所 • アプリ要件的に多⽤用される処理理

    • Zephir側で⾼高速化された標準関数を多⽤用してい る箇所 • Library/Optimizers/以下
  78. ©  Cygames,  Inc. ⼀一部導⼊入してみた結果 • ゲームアプリで多い抽選処理理で⼀一部適応 • 2〜~6ms レスポンスタイムの改善

  79. ©  Cygames,  Inc. Zephirまとめ • やっぱり銀の弾丸はありませんでした(・∀・) • 条件さえ合えば影響範囲を絞って適応できる • ロールバックも可能

    • ⽤用法と⽤用量量を守りつつ選択肢の⼀一つに
  80. ©  Cygames,  Inc. 全体まとめ • Cygamesは、 最⾼高のコンテンツを作りたいと思っています • それには⾼高速なトライ&エラーが⽋欠かせない •

    同時に⾼高速なレスポンスも⽋欠かせない • それらを両⽴立立させるためPHPを使っています!