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

乱数と向き合う 〜PHP によるゲームアプリケーションの実装と運用〜/ColoplTech-04-02

乱数と向き合う 〜PHP によるゲームアプリケーションの実装と運用〜/ColoplTech-04-02

※資料内の参照リンクを選択し閲覧する場合は、ダウンロードをお願いいたします

\積極的に技術発信を行なっております/
▽ Twitter/COLOPL_Tech
https://twitter.com/colopl_tech

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

▽ COLOPL Tech Blog

E704514df1d69d511c4c74771a40c8f5?s=128

COLOPL Inc.

April 27, 2022
Tweet

More Decks by COLOPL Inc.

Other Decks in Technology

Transcript

  1. 乱数と向き合う 〜PHP によるゲームアプリケーションの実装と運用〜 株式会社コロプラ 技術基盤本部 第2バックエンドエンジニア部 サーバー基盤グループ SRE チーム 工藤

    剛 1
  2. 自己紹介 工藤 剛 • 2017 年度新卒入社 (6 年目) • サーバー基盤グループ

    SRE チーム – タイトル横断での SRE 業務 – PHP のアップグレード補助 – 基盤技術開発 2
  3. アジェンダ 1. 乱数について 2. PHP の PRNG の問題 3. コロプラ内製の乱数生成ライブラリ

    (CRandom) 4. CRandom の課題 5. PHP へのコントリビュート おまけ: 乱数と PHP のアップグレード 3
  4. 乱数とは • その名の通り "乱れた数" – 無作為に生成された数値 • ゲームアプリケーションとは切っても切り離せない存在 – こんなところで使います

    • 各種キャラクターの行動パターン選択 • マップやステージの生成 • ガチャやクリア報酬等などのアイテム抽選 • 乱数生成器 – PRNG (Pseudo Random Number Generator) – CSPRNG (Cryptographically Secure Random Number Generator) – TRNG (True Random Number Generator) 4
  5. 乱数生成器 コンピュータは確定的な計算を行うため、真にランダムな値を生成する ことはできない (!) 最近のコンピュータには熱ノイズなどを元に乱数を生成するためのハー ドウェアが実装されていることが多い • x86_64 CPU: RDRAND

    / RDSEED • ARMv8.5A CPU: RNDR 多くの OS ではこれらを利用しつつ乱数を生成する機能が備わっている (/dev/random※ , getrandom(2), CryptGenRandom / CNG) ※ /dev/random がハードウェアを利用しているかは実装に依存します 5
  6. 乱数生成器: PRNG Pseudo Random Number Generator (疑似乱数生成器) の略 • 任意の値で状態をシード

    (初期化) できる – 内部状態を持っており、それに基づき 次の値が生成される • シード値に対して生成される値が保証される – アルゴリズムと状態から次の値が推測可能 • 乱数としての品質はそこそこ 任意の値でシードできて出力結果が推測可能 (シードに対し同一) => ゲームのリプレイ・マップ生成機能などには必須! 6
  7. 乱数生成器: CSPRNG Cryptographically Secure Pseudo Random Number Generator の略 •

    暗号論的に安全な PRNG – 暗号化などに使っても問題ない乱数品質が保証されている • シードにはとても大きい値が必要な場合が多い – 場合によっては指定できないこともある • 生成コストが高い (= 重い) – ゲームに使うには過剰 7
  8. 乱数生成器: TRNG True Random Number Generator の略 • 真の乱数生成器 •

    サイコロとか • 計算で求めていない 計算では導き出すことができない 前述した CPU などの乱数生成器もこれに分類されることがある 8
  9. 乱数生成器: ゲームでの使われ方 9 ゲームにおける乱数はサイコロのようなもの 例:

  10. PHP の乱数実装 主に以下の表の通り 関数 種類 再現性 用途 srand() rand() 実装依存

    (libc) PRNG あり マップ生成 リプレイなど mt_srand() mt_rand() メルセンヌ・ツイスタ PRNG あり マップ生成 リプレイなど openssl_random_pseudo_bytes() 実装依存 (OpenSSL) CSPRNG なし アイテム抽選 キャラ抽選など random_bytes() random_int() OS 依存 CSPRNG なし アイテム抽選 キャラ抽選など 10 : レガシーまたは拡張機能に依存した既に使われていない実装
  11. PHP の乱数実装 主に以下の表の通り 関数 種類 再現性 用途 srand() rand() 実装依存

    (libc) PRNG あり マップ生成 リプレイなど mt_srand() mt_rand() メルセンヌ・ツイスタ PRNG あり マップ生成 リプレイなど openssl_random_pseudo_bytes() 実装依存 (OpenSSL) CSPRNG なし アイテム抽選 キャラ抽選など random_bytes() random_int() OS 依存 CSPRNG なし アイテム抽選 キャラ抽選など 11 再現性が必要なものはこっち • ダンジョン・マップ生成 • 出題する問題や敵キャラの選択 • リプレイ機能 再現性が必要ないものは基本こっち • クリア報酬の抽選 • ガチャ抽選 : レガシーまたは拡張機能に依存した既に使われていない実装
  12. PHP の PRNG の問題 PHP の PRNG はスコープが言語ランタイムに対してグローバル => 乱数を使用する関数を実行すると一貫性が崩れてしまう...

    12 必ず 7 だったものが... 処理を追加したら結果が変わってしまった! 後から追加
  13. 内製の PRNG ライブラリ CRandom というライブラリを作成 • XorShift128+ を採用 – シード値に対し生成結果の一貫性が保証されている

    – Chromium など既に幅広く使われている枯れたアルゴリズム • インスタンス単位で状態を保持 – 意図しない (一貫性のない) 結果にならず安全に リプレイなどの状況再現ができる 13
  14. CRandom の問題 • PHP による実装のため速度が遅い – PHP が符号なし整数をそのまま扱えないので回避策が必要 • PHP

    のバージョンアップにより互換性が崩れるリスク – 最近だと演算子の挙動変更とかもあるので... • 生成される乱数の統計検定にかかるコストが高い – TestU01 など PHP 本体にクラスベースの乱数生成器の実装を提案してみよう 14
  15. PHP へのコントリビュート C で拡張機能として実装し RFC を提案 https://github.com/php/php-src/pull/8094 PHP 8.2 での採用を目指し、現在は議論中のステータス

    15
  16. いろいろな課題が見えてきた • 英語でのコミュニケーション – DeepL のおかげで昔に比べてだいぶ楽になった • 意見のとりまとめ – どのような

    API が良いかについて長期の議論になった – 実装する PRNG アルゴリズムの選定 • 実装したはいいがボツにしたものも結構ある • さまざまな環境でのデバッグ – PHP がサポートする OS 、アーキテクチャでのデバッグ作業 • NTS / ZTS • Windows • IBM z/Architecture (s390x) コントリビュートを試みて 16
  17. 乱数と PHP のアップグレード PHP 7.1 から srand(), rand() が mt_srand(),

    mt_rand() の エイリアスに srand() でのシード結果に依存していたタイトルが PHP 7.1 以降に 更新できない状態に... 17
  18. 乱数と PHP のアップグレード srand(), rand() と完全互換な関数を提供する PHP 拡張を作成 無事サポートされているバージョンにアップグレードできた! 18

  19. まとめ 乱数の世界は奥深い • ゲームと乱数は切っても切り離せない存在 • しっかりと理解し、適材適所を見極める必要がある • 必要であれば言語自体へのコントリビュートもしていく 乱数と PHP

    のアップグレードのより詳細な部分に関しては 弊社オウンドメディア「Be-ars」に記事を掲載しています。 https://be-ars.colopl.co.jp/team/en-blog_vol.2.html 19