世界を動かす技術を、日本語で。

「Valorant」の128ティックサーバー (2020)

概要

  • VALORANT のGameplay Integrityチームによるサーバーパフォーマンス最適化の技術的解説
  • サーバーフレーム処理時間を 50msから2ms未満 まで短縮した取り組み
  • コード最適化、ハードウェア調整、OSチューニングの詳細
  • パフォーマンス可視化 とデータ分析による継続的な改善プロセス
  • 実運用環境 での負荷試験とCPUアーキテクチャへの対応事例

VALORANTサーバーパフォーマンス最適化の舞台裏

  • Gameplay Integrityチーム のBrent “Brentmeister” Randallによる技術的解説
  • チームの主な担当領域
    • ビルドシステム 管理
    • 自動化フレームワーク 運用
    • ゲームクライアント・サーバーパフォーマンス 最適化
  • 本記事では サーバーパフォーマンス に焦点

サーバーパフォーマンスの重要性

  • VALORANT は早期開発段階から非常に厳格な サーバーパフォーマンス要件 を設定
  • オンラインシューター特有の ピーカーズアドバンテージ (先に覗いた側が有利になる現象)対策
  • 128-tickサーバー の必要性
    • 高い反応性と公正なゲーム体験の実現
    • ネットワーク遅延・サーバーtick rateの影響を最小化

コード最適化とリソース制約

  • 128-tick 運用には 1フレームあたり7.8125ms 以内で処理完了が必須
  • 単一ゲームでCPUコアを専有するのはコスト的に非現実的
  • 3ゲーム/コア (gpc)以上の効率化が必要
    • 36コアホストでは 108ゲーム同時稼働 が目標
  • OSやスケジューリングのオーバーヘッドも考慮し 2.34ms/フレーム が目標値
  • 初期値 50ms からの大幅な短縮が必要

問題分解と計測システム

  • 大規模課題は カテゴリごと に分解して最適化
  • 主なCPUコストカテゴリ
    • replication
    • FoW
    • network
    • animation
    • gameplay
    • movement
    • equippable
    • character physics
    • other
  • ValSubsystemTelemetry によるコードのスコープ化・細分化
  • 各カテゴリごとの 実行時間計測 と分析

Riot Analytics Platformの活用

  • Riot内製のAnalytics Platform でビッグデータ分析・可視化
    • 平均サーバーフレーム時間
    • 各サブシステムの処理時間
  • 定期的なパフォーマンス監視により 問題の早期発見・修正
  • パフォーマンスデータに基づく エンジニア割り当てとタスク管理

サブシステムごとのパフォーマンス予算管理

  • 各サブシステムに 目標値(予算) を設定
  • 専門チームごとに 最適化タスク を並行実施
  • replicationanimation の最適化事例が代表的

Replication最適化

  • Unreal Engine 4(UE4) のreplication機能は便利だが パフォーマンスコスト高
  • 毎フレーム全変数を全クライアントと比較するため キャッシュ効率が悪い
  • RPC(Remote Procedure Call) への置き換え
    • 状態変化時のみ通信する pushモデル で大幅な効率化
    • 設計・実装時の考慮点増加も、 100倍~10000倍の高速化 を実現

Animation最適化

  • サーバー側でも アニメーション計算 が必須(被弾判定のため)
  • 履歴バッファ を用いた巻き戻し判定方式
  • 毎フレーム計算から 4フレームに1回のみ計算 へ変更
    • 必要時は 補間(lerp) で対応
    • 75%コスト削減 を達成
  • バイフェーズ (購入フェーズ)中はアニメーション処理自体を停止
    • 33%追加削減 に成功

実運用環境でのパフォーマンス検証

  • 負荷試験 を自作し、100+インスタンス同時稼働時の実測
  • フレームタイムの増大(例:1.5ms→5.7ms/168インスタンス)の原因分析
  • CPUアーキテクチャ の影響
    • 各コアの L1/L2キャッシュ は専用、 L3キャッシュ は共有
    • インスタンス増加により L3キャッシュ競合 が発生、パフォーマンス低下

Intelとの協業とハードウェア最適化

  • Intel Xeon E5 プロセッサの インクルーシブキャッシュ 特性
    • L2キャッシュ の内容が L3キャッシュ にも保持される設計
    • L3キャッシュの競合・エビクションがL2にも影響しやすい
  • Intelクラウドチーム との共同検証でボトルネック特定
  • ハードウェア・OS設定の最適化による 大規模同時稼働 の実現

まとめ

  • VALORANT サーバーの大規模最適化プロジェクト全体像
  • コード、分析基盤、ハードウェアの 多角的アプローチ
  • 継続的な計測・改善サイクル による高パフォーマンス維持
  • 他タイトルや開発現場 にも応用可能なノウハウ蓄積

Hackerたちの意見

128ティック/秒のサーバー。 (そして、突然この記事の主張が明確になった。) 「ティック」、つまり更新は、ゲームの状態が一歩進むことを指す。UPS(ここからはそう呼ぶね)またはティックレートは、その頻度を示す。つまり、128ティック/秒 == 1秒間に128回の更新。これはかなり高い数字だよ。比較のために言うと、Factorioは60 UPS、Minecraftは20 UPS。最初はFPSの状態はかなり小さいと思ってたから、もっと高いティックレートがサポートされるべきだと思った。でも、戦闘視界や可視性(Factorioはクライアントを信頼してるしね)や、ヒットボックスの検出のためにアニメーションが必要なことも忘れてた。(でも、プレイヤーのアニメーションは常に行われてるのかな?大きな長方形のバウンディングボックスか球体があって、弾がその範囲に入ったときだけアニメーションが発生するんじゃないかと思う。これについては考慮されてるだろうし、実装されてないだけだと思う。でも、「購入」部分のアニメーションをしないっていうメモもあったし…)

それに、フォートナイトは allegedly 30ティック/秒らしいよ。

クライアントの更新は73と測定されていて、128のサーバーティックと更新レートにはちょっと合わないみたい。もしかしたら、ここ5年で変わったのかも。CSGOのプライベートサーバーも128ティックレートで動いてたよ。 https://www.youtube.com/watch?v=ftC1Rpi8mtg

例えば、Fallout 76では、他のプレイヤーがどこを見ているか、または銃をどこに向けているかがわかるんだよね。撃たなくても、ユーザーの入力に応じてモデルがアニメーションする。秒間のティック数はあまり良くないと思う。というのも、同じ場所で十数人以上が何かを撃っていると、かなりのラグが発生することで有名だから。

OSRSは0.6 TPSで動いてるんだよね…つまり、1分間に100ティック。これがどれだけ違うか、ちょっと面白いよね。

バトルフィールド4が発売されたとき、ネットワークパフォーマンスがひどかったんだよね。バトルフィールド3も良くはなかったけど、BF4はそれよりもずっと悪かった。クライアントがサーバーに30Hzでアップデートを送っているのに、サーバーが返すのは10Hzだけだったんだ。[1] これはBF3と同じだったけど、サーバーの負荷の問題もあってさらに悪化して、高Pingの補正もあんまり機能してなかった。プレイヤーからの反発があって、Battle(non)sense[2]の素晴らしい分析が注目を集めて、開発者たちはネットワークコードの改善に着手することになったんだ。結局、高ティックレートのサーバー[3][4]が導入されて、最大144Hzになったけど、俺は主に120Hzのサーバーでプレイしてた。その他にもたくさんの改善があったよ。120Hzのサーバーと30Hzのサーバーの違いは、マウスとキーボードの違いがわかる人には夜と昼の差だった。ただ、その頃にはゲームは半分死んでたけど…でも、その時まだプレイしてた15人くらいには最高だったよ。

比較として、Runescape(RS3とOldschool Runescapeの両方)は0.6ティック/秒(100ティック/分)のシステムを持ってるんだ。これがこのゲームにはうまく機能してると思う。つまり、いくつかのゲームはa) ゲームプレイのメカニクスによって高いラグに耐えられるか、b) エンジンの限界やそのラグに基づいてゲームプレイのメカニクスを進化させることができるってことだ。RS3は最初、0.6秒のティックシステムに寄りかかってた(DeviousMUDからRunescape Classic、RS2への移行の名残)けど、最終的には従来のポイント&クリックの戦闘システムの上に能力ベースの戦闘システムを発展させた。一方、OSRSはこの0.6秒ティックシステムに合った新しいメカニクスを進化させて、ポイント&クリックの戦闘システムとシームレスに統合してる。両方のゲームを何年もプレイしてきたけど(文字通り、ログインしてた時間が何年もある)、ティックシステムが速いFPSゲームは一般的にかなり流れるように感じるから、極端なネットワークの問題以外でティックシステムが変だと思ったことはないな。これを実現するための技術的な課題はすごいよ、TFAで説明されてる通り。

大きな長方形のバウンディングボックスか球体があって、弾がその範囲に入ったときにアニメーションが発生するってことかな。これを考えるのは面白いね。ヒットスキャン攻撃はベクトルだよね? だから、最初の交差チェックをあまり詳細じゃないヒットボックスでやって、もし「うん、これが交差するかも」と報告されたら高解像度のアニメーションチェックをする方がパフォーマンス的に得になるのかな? それとも、そのチェック自体が高コストすぎて、フル解像度で一回だけやる方が早いのかな? どちらにしても、こういうのはエンジニアの興味を引くよね。

より良い比較対象は別のシューティングゲームだね。Counter-Strikeは10年間も128ティックサーバーを持ってるから。

ここからは完全に推測だけど、FPSではサーバーがクライアントに多くの計算集約的なこと、例えばフォグ・オブ・ウォーや衝突判定、視線の確認なんかを頼ってると思う。これが、ウォールハックみたいなチートが可能になる理由だよね。クライアントはゲームの全状態をローカルに持っていて、どこを見てその状態を取り出すかを知っているから、マップ上の全プレイヤーの位置を把握できるんだ。もしサーバーがクライアントに他のプレイヤーの位置を知らせず、クライアントと相手が視線内にいると判断するまで待っていたら、チートの多くは基本的に不可能になるだろうね。

どのゲームサーバーがErlangで実装されてるか気になるな。

ネットワーク接続、ロビー、マッチメイキング、リーダーボード、チャットはそうだけど、実際のシミュレーションは、速いペースのシューティングゲームには多分向いてないだろうね。パフォーマンスの理由だけじゃなくて、BeamVMをハードリアルタイムとは呼ばないけど、コードのためにもそう。ゲームサーバーは通常クライアントだけど、ヘッドレス(レンダリングなし)で動いてることが多い。再利用やアーキテクチャに役立つよ。

彼らがUnreal Engineにかなり投資してるみたいで、それが全体のスタックになっちゃった感じだね。もっと速いCやRustがベアメタルで動いてるのを想像してたけど、そのUE4のコードスニペットは目に厳しいね。

Eve OnlineがErlangで動いてるってはっきり覚えてたんだけど、調べたら100%間違ってたわ。でも、「Vendetta Online」ってゲームがErlangを使ってるってスレッドを見つけたよ…詳細が書かれたブログはもう消えちゃってるみたいだけど。とにかく、楽しんでね! http://lambda-the-ultimate.org/node/2102

今まさにこれをやってる!Elixirで実装したMMOゲームサーバーに取り組んでるんだ。すごく素晴らしくて、追加の観測性や信頼性の機能が無料で得られる。なんでこれがもっと人気じゃないのか分からない。プロジェクトを始める前に、BeamVMはパフォーマンス的にダメだって言ってた人もいたけど、それは間違いだった。多くのタイプのゲームでは、各ティックで高負荷な計算をしてるわけじゃないからね。クライアント間のインタラクションのルールをチェックしたり、簡単なAABBや視認性のチェックをするだけなんだ。

モダンなFPSゲームサーバーは、GC言語で書かれたら良いパフォーマンスは出ないよ。Erlangもかなり遅いし、Python並みのパフォーマンスだ。C#、Go、Javaとは大きく違う。もう一つの理由は、クライアントとサーバーが同じ言語で書かれなきゃいけないってこと。

マッチメイキングサーバーにはErlangが結構人気だって聞いたことあるよ。昔、Call of DutyのマッチメイキングもErlangで動いてたみたい。ただ、実際のゲームサーバーはパフォーマンスの理由でほぼ確実にC++だね。

2020年も追加すべきだね。この記事を前に読んで、アーキテクチャにいくつかの更新があったと思ったんだ。

この深掘り記事はすごくいいね。いつでも、約50のゲームが購入フェーズに入ってるだろうね。プレイヤーはスポーンバリアの後ろで安全に装備を購入していて、攻撃は当たらない。購入フェーズ中はサーバー側でアニメーションを行う必要すらないことに気づいたよ、オフにしちゃえばいいんだ。これが最近の「オンライン」ビデオゲームのトレンドの理由を説明してるね:10分遊ぶために、10分のロビー時間や強制アニメーション(エンディングアニメーションみたいな)を待たなきゃいけない。BO6では本当にイライラする、ただ遊びたいだけなのに、時には30分もないクイックゲームセッションのために、今のゲームではすごく長い時間待たなきゃいけない。ほんとにうんざりだよ。

これは他のゲームの「ロビータイムやエンドゲームのアニメーション」とは違うよ。Valorant(Counter Strikeに似てる)では、ゲームの開始時に60秒間武器やアビリティを買う時間がある。ValorantやCSは通常ベストオブ13で、各ラウンドの前には60秒の「バイ」期間があるんだ。

とても興味深い読み物だった。マネジメントやエンジニア、ベンダーがフレームバジェットを達成するために同じ方向を向いていたみたいだね。特に、ゲームコードの各行を適切なバケットにプロファイリングする部分は、かなりの労力がかかりそうだけど、その分のリターンがあったんだろうね。「パフォーマンスの調整リスト」を作って、ネットのゲーム開発ブログで学んだことをそのまま実行すると、アプリケーションの特定のニーズを考慮せずにやると、パフォーマンスを悪化させることもあるから注意が必要だね。

この投稿は、エンジニアリングの深堀りというより、Xeonの製品パンフレットがゲームブログに迷い込んだ感じだね。彼らは「ハイパースレッディング」って額にタトゥーを入れるくらい、あらゆるIntelの最適化を軽く言及してる。

もちろんそうなるよね。彼らは全部インテルのハードウェアを買ったんだから。めちゃくちゃパフォーマンスのいいマルチプレイヤーサーバーを作ってるし、可能な限りの最適化を言及すべきだよね。もしAMDのスレッドリッパーサーバーを使ってたら、その機能も全部言ってたはず。

コードをいじくり回しても、ラグからは逃げられないよ。現代のマッチメイキングはスキルで人をグループ分けするから、ラグの混ざり具合がすごいことになる。昔の地域サーバーとは全然違う感じ。確かにスキルのミックスは多様だったけど、少なくとも実際のスキルで10ms未満のクリスプなラグでボコボコにされたもんだ。今は、200msのラグで次のマップセクターに飛び込んできて、ママを侮辱しながらユニコーンスキンを着たやつにナイフでノースコープされるって感じだよ。

CS 1.6の頃、安定した<10msのサーバーでプレイしてたのが懐かしい。ヒューストン/ダラス/オースティン/サンアントニオ地域は、競争の激しいFPSアクションのミニユニバースみたいだった。俺の2mbpsのローダーナーケーブルモデムは、ヒューストンからダラスまでシングルデジットのピングを達成できたんだ。あの頃はモデムをゲームPCに直接繋いでた。

現代のマッチメイキングはスキルで人をグループ分けする 俺はゲームスタジオで働いてるんだけど、最近見たことは、もう誰も有線接続してないってこと。今や有線で繋いでるのはパワーユーザーだよ。99%のユーザーはモバイルかWi-Fiで、最初のホップか2ホップで10msなんだ。

それを考えてくれてよかったね。ちなみに、私はRiotでValorantの開発サイクルの一部に関わってたんだけど、この技術ブログでの目標はかなり大きなものでした。レイテンシーを維持することが目的だったんだよね。

カウンターストライク: グローバルオフェンシブも128TPSを問題なく処理できたんだ。ただ、公式マッチメイキング(64TPS)には実装しないことにしただけ。コミュニティサーバーでは非常にスムーズに動作してた。カウンターストライク2は64TPSの上に物議を醸す「サブティック」システムを実装してるけど、実際の128TPSとは比較にならないし、実践では標準の64TPSよりも悪化することが多い。

お金を倍使えば大抵のことはうまくいくよね。問題はそれが機能するかどうかじゃなくて、経済的なことなんだ。ほとんどのゲームサーバーはシングルスレッドで、目標はドルあたりの最大プレイヤー数をサポートすることだから。コミュニティサーバーは、もっと多くのプレイヤーや高いティックレートをサポートするために、もっと計算リソースを使うことを気にしないよね。もし同時に100万人のプレイヤーがいるとしたら、Counter-Strikeみたいに選択肢が変わるかも。

カウンターストライクソースのサーバーが33、66、または100ティックで動いてたのをぼんやり覚えてる。高校のゲーミングクランは「10tik」って名前で、古いペンティウムの箱でCSSサーバーを運営してたことをからかってたんだ。

この記事には結構重要な詳細が隠されてるね。「まだ古いIntel Xeon E5プロセッサーで動いてました、...」って。より現代的なXeonスケーラブルプロセッサーに移行したら、サーバーアプリケーションのパフォーマンスが大幅に向上したって。でも、比較してたプロセッサーについては記事の中で何も触れられてなかったな。