Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

©  Cygames,  Inc. 今回お話したいこと • 前半 • Cygamesのサーバー構成/技術スタック • コンテンツ開発に対してのマインドセット • 負荷分散/⾼高速化/リリースでの取り組み • 後半 • ⾼高速化のためZephir導⼊入検討 • Zephirの概要と導⼊入 • 運⽤用してみてとこれから

Slide 4

Slide 4 text

©  Cygames,  Inc. ⾃自⼰己紹介 • ⼩小笠笠原空宙(たかひろ) • サーバーサイドエンジニーア • ほぼPHP • ちょっとperl • 2014年年7⽉月 Cygames join • その前はモバイルサイト/ソーシャルゲーム開発

Slide 5

Slide 5 text

©  Cygames,  Inc. ©  Cygames,  Inc. 5 ちょっと紹介

Slide 6

Slide 6 text

©  Cygames,  Inc.

Slide 7

Slide 7 text

©  Cygames,  Inc.

Slide 8

Slide 8 text

©  Cygames,  Inc.

Slide 9

Slide 9 text

©  Cygames,  Inc. ©  Cygames,  Inc.

Slide 10

Slide 10 text

©  Cygames,  Inc. ©  Cygames,  Inc. MySQLに変わるDB 「 CySQL 」を開発中! •シャドーバースポータルで ⼀一部稼働済み

Slide 11

Slide 11 text

©  Cygames,  Inc.

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

©  Cygames,  Inc. とあるアプリの現状 • ⽉月間300億PV • ピーク時、秒間5万アクセス • ピーク時、秒間100万クエリ • 1⽇日のDBのトランザクションデータ増加量量 • 1〜~2TB • 1⽇日のログデータ増加量量 • 60GB〜~

Slide 14

Slide 14 text

©  Cygames,  Inc. Cygamesを⽀支えるサーバーサイド • サーバー構成/技術スタック • 何を、どのように利利⽤用しているのか • 開発スタイル/マインドセット • どのような価値観で開発しているか • 負荷分散/⾼高速化/リリースでの取り組み • 開発~∼運⽤用までの取り組み • 今/これからの取り組み • 今後どう前進しようとしているか

Slide 15

Slide 15 text

©  Cygames,  Inc. ©  Cygames,  Inc. 15 とあるサーバー構成例例

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

©  Cygames,  Inc. とあるアプリの周辺技術 Ansible Vagrant Munin Mackerel Jenkins New  Relic Google  BigQuery Fluentd Elasticsearch Kibana

Slide 25

Slide 25 text

©  Cygames,  Inc. ©  Cygames,  Inc. 25 開発スタイル マインドセット

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

©  Cygames,  Inc. ⾯面⽩白くなければ意味がない • ⾯面⽩白さにゴールはない… • 素早くトライ&エラーを繰り返す • 素早く微調整を繰り返す • それが⾏行行いやすい実装 • ⾯面⽩白くなければばっさり捨てることも厭わない

Slide 29

Slide 29 text

©  Cygames,  Inc. ©  Cygames,  Inc. 29 CS最優先

Slide 30

Slide 30 text

©  Cygames,  Inc. CS(カスタマーサポート)最優先 • お客様からの問い合わせには即対応 • 即対応できるようなログの設計 • ログの可視化ツールの構築 • 本番環境のデータを複製し、実機で動きを確認 できる検証環境 • 確証を持って対応できるように

Slide 31

Slide 31 text

©  Cygames,  Inc. ©  Cygames,  Inc. 31 当たり前のことを 当たり前にやる

Slide 32

Slide 32 text

©  Cygames,  Inc. 当たり前のことを当たり前にやる • ⼩小さな差がピーク時に⼤大きな差に • 不不必要な処理理は書かない • 不不必要なデータは取得しない • 適切切なリファクタリング • 運⽤用し易易い実装、拡張しやすい実装 • ⽇日々の積み重ねが、 良良くも悪くもピーク時に顕在化する

Slide 33

Slide 33 text

©  Cygames,  Inc. 当たり前のことを当たり前にやる • 当たり前のレベルがスピードにつながる • ほぼ毎⽇日複数回デプロイ • ほぼ常にイベント開催 • 新機能追加、機能改善、etc • PJに関わる⼈人間も多くなる • 当たり前のことを増やし、積み上げることで チームのレベルを上げていく

Slide 34

Slide 34 text

©  Cygames,  Inc. ©  Cygames,  Inc. 34 負荷分散/⾼高速化/ リリース での取り組み

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

©  Cygames,  Inc. 負荷分散/スケールアウトの取り組み • DBは⽔水平、垂直分割 • キャッシュはTwemproxyで分散 • Node.jsはNginxでバランシング • 各種ログは⾮非同期で保存 • バッチ処理理できるものはバッチ処理理へ • 分散/スケールアウトできるように • できるだけキャッシュ • 同期処理理は必要最低限に

Slide 37

Slide 37 text

©  Cygames,  Inc. ©  Cygames,  Inc. 37 ⾼高速化の取り組み

Slide 38

Slide 38 text

©  Cygames,  Inc. プロファイリングの取り組み • 「推測するな、計測せよ」 • New  relicで解析 • 以前はxhprofなど • 重いクエリ、最適化できる処理理などを地道に対応 • FW側の不不要な処理理なども最適化 • 4.5秒以上かかったリクエストを⽇日次で集計、通知 • 検知 ⇔  最適化の地道な対応 イベント開始><; 負荷対策リリース\(^o^)/ レスポンスタイム推移

Slide 39

Slide 39 text

©  Cygames,  Inc. DB関連での取り組み • ボトルネックの多くはDB関連 • トランザクション中の処理理は最⼩小限に • まとめられるクエリはまとめる • indexはカーディナリティが⾼高い順に • ⽇日次で開発環境で実⾏行行された全クエリをexplain • 問題のありそうなクエリは通知

Slide 40

Slide 40 text

©  Cygames,  Inc. DB関連での取り組み • 本番DBのGeneral_̲Log,Slow_̲Queryも解析

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

©  Cygames,  Inc. DB関連での取り組み • 本番DBのGeneral_̲Log,Slow_̲Queryも解析 • 実際に実⾏行行されたクエリを⼀一覧 • 渡されたパラメータ等確認 • 運⽤用の過程でレコードの偏りなどで不不適切切なindex が選択されることも

Slide 43

Slide 43 text

©  Cygames,  Inc. DB関連での取り組み • 本番DBのGeneral_̲Log,Slow_̲Queryも解析 • 対象クエリのexplain表⽰示 • index,type,partition など確認

Slide 44

Slide 44 text

©  Cygames,  Inc. DB関連での取り組み • とにかくデータがもりもり増えていく • トランザクションデータは毎⽇日1~∼2TB単位で増加 • CS/分析⽤用途の⾏行行動ログも毎⽇日60GB〜~で増加 • 必要なくなったデータは順次パージしないと ディスク容量量を圧迫してしまう

Slide 45

Slide 45 text

©  Cygames,  Inc. DB関連での取り組み • 必要なくなったデータは順次パージ • イベント単位でテーブル作成、終了了後にdrop • パーティション単位で毎⽇日drop&add • 不不要なテーブルは週次でアラートを通知 • 常に必要なデータのみを保持するように

Slide 46

Slide 46 text

©  Cygames,  Inc. DB関連での取り組み • 数⼗十GBのテーブルを安全にdropする • データファイルが⼤大きいとファイル削除時、 io_̲waitで数秒間ではあるがレスポンス劣劣化 i. drop対象のデータファイルにhard  link貼る ii. drop  table実⾏行行 iii. hard  linkしたファイルのサイズを切切り詰めた後 に、remove(linuxのtruncateコマンド) • ゆるやかに削除することで数百テーブル、合計数百 GBのテーブル削除もレスポンス劣劣化なく実⾏行行

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

©  Cygames,  Inc. ©  Cygames,  Inc. 48 今/これからの取り組み

Slide 49

Slide 49 text

©  Cygames,  Inc. 今/これからの取り組み • PHP7対応 • FWのcoreを拡張させている箇所の対応 • 各種extensionの対応状況の調査 • 品質と⽣生産性の向上、仕組みづくり • ゲーム特有の問題を検知できる仕組み • ユニット/E2Eテストだけではない何か • Zephirによる⾼高速化/共通化 • この後詳しく・・・

Slide 50

Slide 50 text

©  Cygames,  Inc. ⼀一旦まとめ • Cygamesサーバーサイドは、最⾼高のコンテン ツを開発し、それを⾼高速/安定的な提供を⽬目標 としています • ⽇日々、トライ&エラー/実装⇔計測を地道に繰 り返し実績を積み上げ、上記の実現を⽬目指して います!

Slide 51

Slide 51 text

©  Cygames,  Inc. ©  Cygames,  Inc. Zephirやってみた ⼩小笠笠原 空宙

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

©  Cygames,  Inc. Zephirとは • PHPerでも簡単にextensionが書ける⾔言語 • PHPのような記述でextensionが作成できる • if⽂文の書式が違う • 変数に$使わない • 変数上書き時は、let  を使う • 静的/動的型⾔言語 • メモリ管理理等が必要ない • ⾼高速FW PhalconはZephirで実装

Slide 59

Slide 59 text

©  Cygames,  Inc. Zephirについて • Hello  World namespace  Utils; class  Hello { //say  func public  static  function  say() { echo  "Hello  World!"; } }

Slide 60

Slide 60 text

©  Cygames,  Inc. Extensionが⽣生成/実⾏行行までのフロー 1. Zephirのスケルトンを作成 $zephir init utils utils ├──  ext //Zephirのcore,⽣生成されるextensionなどが配置される │ └──  utils //ここに.zepファイルを作成していく

Slide 61

Slide 61 text

©  Cygames,  Inc. Extensionが⽣生成/実⾏行行までのフロー 2.Zephirのファイルを作成 $vim  utils/hello.zep namespace  Utils; class  Hello { public  static  function  say() { echo  "Hello  World!"; } }

Slide 62

Slide 62 text

©  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

Slide 63

Slide 63 text

©  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); } }

Slide 64

Slide 64 text

©  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(); }

Slide 65

Slide 65 text

©  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型で⽐比較を ⾏行行っている

Slide 66

Slide 66 text

©  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で値の やり取りをしている

Slide 67

Slide 67 text

©  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(); } 再帰部分の 関数コール

Slide 68

Slide 68 text

©  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の⾜足し算も関数 コールになっている

Slide 69

Slide 69 text

©  Cygames,  Inc. Zephirでフィボナッチ数列列 • ZVALでの値のやりとり、関数コールもほぼ同 じようなのでそこまで⼤大きな差はでなかった • が、ほぼソース変えず⾼高速化 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 PHP Zephir 90%程度度に [s]

Slide 70

Slide 70 text

©  Cygames,  Inc. ©  Cygames,  Inc. 70 もう少し実⽤用的なもの

Slide 71

Slide 71 text

©  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); }

Slide 72

Slide 72 text

©  Cygames,  Inc. Zephirでログ出⼒力力 • fwrite()でtsv形式でファイル出⼒力力 • 単純な関数コールなので差は出にくい 0 10 20 30 40 50 60 PHP Zephir ほぼ変わらず [ms]

Slide 73

Slide 73 text

©  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はしない } } }

Slide 74

Slide 74 text

©  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]

Slide 75

Slide 75 text

©  Cygames,  Inc. ⼀一旦ここまでわかったこと • PHPとの互換性のためZVALでの計算など、 実質PHPがやっていることと同様の事を⾏行行って いる様⼦子。C⾔言語的に最適化の余地はある • 配列列処理理などループ処理理などは速くなる • Zephirで標準関数のいくつか⾼高速化されている • PHPのコードをほぼ変えずに、Zephirの構⽂文 規則に整えればextension化ができる • 引数の型などはチェックは確実に⾏行行う • PHPだとwarningでもFATAL  ERRORになる

Slide 76

Slide 76 text

©  Cygames,  Inc. 改めてZephir/extension化すること • Pros • ⾼高速化できる • PJ/FWなど関係なく利利⽤用可能 • 特定箇所のみに適応できる • PHPに戻すことも可能 • Cons • デプロイフローが増える • 修正がしにくい

Slide 77

Slide 77 text

©  Cygames,  Inc. 導⼊入箇所例例 • コード修正がほぼない共通処理理 • ループを多⽤用する箇所 • アプリ要件的に多⽤用される処理理 • Zephir側で⾼高速化された標準関数を多⽤用してい る箇所 • Library/Optimizers/以下

Slide 78

Slide 78 text

©  Cygames,  Inc. ⼀一部導⼊入してみた結果 • ゲームアプリで多い抽選処理理で⼀一部適応 • 2〜~6ms レスポンスタイムの改善

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

©  Cygames,  Inc. 全体まとめ • Cygamesは、 最⾼高のコンテンツを作りたいと思っています • それには⾼高速なトライ&エラーが⽋欠かせない • 同時に⾼高速なレスポンスも⽋欠かせない • それらを両⽴立立させるためPHPを使っています!