14.1K Views
November 17, 24
スライド概要
[お題目]
・負荷試験の背景・目的
・MagicOnionの概要
・MagicOnionを利用したクラウドアーキテクチャ
・GKE・DFrameを利用した負荷試験環境の構築
・負荷試験結果・考察
・限界性能と .NET更新によるパフォーマンス向上
・インスタンスガチャの存在
・dotTraceによるプロファイリング
・同時接続人数
・負荷試験の費用
VRコミュニケーションを支えるエンジニアをやっています
MagicOnionサーバー のパフォーマンス調査 と.NET更新によるパ フォーマンス改善 とうとう 1
自己紹介 ● とうとう( X :@__tou__tou ) ○ VRコミュニケーションを支えるエンジニア ○ 領域:インフラ・リアルタイムサーバー ● 上級バーチャルリアリティ技術者(日本バーチャルリアリティ学会) ● VRChat でよく遊んでいます 2
お題 ● ● ● ● ● 負荷試験の背景・目的 MagicOnionの概要 MagicOnionを利用したクラウドアーキテクチャ GKE・DFrameを利用した負荷試験環境の構築 負荷試験結果・考察 ○ ○ ○ ○ 限界性能と .NET更新によるパフォーマンス向上 インスタンスガチャの存在 dotTraceによるプロファイリング 同時接続人数 ● 負荷試験の費用 3
背景 ● メタバース等ではユーザーの位置情報を共有するために MagicOnion等のリアルタイムサーバーを利用 ● サーバー1台で運用可能なルーム数や同時接続人数を把握す ることは「安定したユーザー体験の提供」や「サーバー料金のコ スト効率を高める」ために重要 4
目的 ● 負荷試験により、MagicOnionサーバーの1台あたりの同時接 続人数を測定 ● .NET 更新によるパフォーマンス改善 5
MagicOnionの概要 6
MagicOnionの概要 ● .NETベースの 双方向 RPC フレームワークであり、リアルタイ ム通信を提供 ● サーバー・クライアントをともに C# で実装可能 ○ クライアントは Unity にも対応している ● 開発は Cysharp 社で MIT ライセンス ○ MagicOnion - GitHub 7
MagicOnionを利用した クラウドアーキテクチャ 8
シングルサーバー構成 構築は簡単だけど、サーバー数がス ケールしないので、トラフィックが増え るとボトルネックになる MagicOnionサーバーの1 プロセスは 複数の room(実装上はGroup)を持 つことができる room a room b https://github.com/Cysharp/AlterNats?tab=readme-ov-file#architecture-guide より 9
サービスディスカバリ構成 room c に接続 したい room a room b サーバー台数がスケールした場 合でも、 接続したい room を持つ サーバーのネットワーク上の位 置を教えてくれる room c room d room e room f https://github.com/Cysharp/AlterNats?tab=readme-ov-file#architecture-guide より 10
ロードバランサ + Pub/Sub 構成 LB room a あるMagicOnionサーバーから別の MagicOnionサーバーへメッセージを 転送 NATS の代わりに Redis Pub/Sub が 使われることもある room a room a room a https://github.com/Cysharp/AlterNats?tab=readme-ov-file#architecture-guide より 11
負荷試験環境の構築 12
負荷試験対象:シングルサーバー構成 今回の負荷試験では、 MagicOnion サーバー 1 台あたりの性能 を評価 スケーリング性能は評価しない https://github.com/Cysharp/AlterNats?tab=readme-ov-file#architecture-guide より 13
負荷試験環境 Google Kubernetes Engine : コンテナ化したアプリのデプロイ、管 理、スケーリングを担う, MagicOnionに接続するための Client を沢山用意するために利用 DFrame (Cysharp) : C# 製の負荷試験フレームワーク, C#で負荷シナリオを記述できるので 自由度が高い,Unityでも利用できる (が今回は通常の.NET版を利用) 14 Google Kubernetes Engine を使用したロード バランシング テスト を参考に構築
負荷試験環境 WebUI を提供 相当 15
MagicOnionサーバーのデプロイフロー 16
負荷試験環境のデプロイフロー 17
負荷試験結果 18
ストレステスト サーバーの限界性能を評価 19
実験条件 ● Platform : .NET6.0, .NET8.0, .NET 9.0 ● Server Spec ○ ○ n1-standard-1(vCPU 1 個, Mem 3.75GB) CPU : Intel SkyLake ● MagicOnion6.1.5 のStremaingHub の HTPP/2 通信 (not https) ● csproj はほぼデフォルト設定 ○ 最適なパラメーターがあるはずだが今回は未検証 ● 1 room に 32 client が接続 ● 10分間、各 client が server に対して可能な限り高頻度で位置情報 をランダムに更新するリクエストを送信 ● 各 Platform において 5 回ずつ計測(合計 5×3=15 回計測) 20
結果の 一 例 1 client の結果 Latencyの統計値と RPS (Request Per Second) 32 client 合計の 秒間リクエスト数 21
.NET6,.NET8,.NET9 のパフォーマンス比較 .NET 8.0 .NET 6.0 5605 ± 192 RPS (平均±標準偏差) 15 % 向上 6430 ± 162 RPS (平均±標準偏差) 23 % 向上 .NET 9.0 7 % 向上 6896 ± 219 RPS (平均±標準偏差) 22
ストレステストにおける注意事項 ● worker( client )の計算リソースが十分であるか ○ 不足していると、サーバーに十分な負荷がかからない ● サーバーCPUに十分負荷がかかっているか ● インスタンスガチャ ○ CPUを指定しない場合、インスタンス性能バラつきが大きくな る ● メモリが十分か ● ネットワーク帯域が十分か 23
client の計算リソースが十分か VMインスタンス上で複数 の client が稼働 CPU 使用率 80% 未満な ので計算リソースは十分 ≒ サーバーに十分な負荷が かけられている 24
サーバー CPUに対する十分な負荷 CPU 使用率が 100 % に 張り付いている ≒ 十分な負荷 25
インスタンスガチャ ストレステストの結果 (MagicOnion on .NET 9.0) 同実験条件であるはずだ が、結果にバラつきがある ????? 6896 ± 219 RPS (平均±標準偏差) インスタンスの性能に バラつきがある? → インスタンスガチャ 26
インスタンスガチャ ● 本実験で利用したマシンタイプは n1-standard-1 ● N1 はデフォルトで以下のいずれかの CPU が割り当てられる CPUの周波数が異なれば パフォーマンスに影響 ただし、本実験では CPUを 指定してインスタンスを作 成しているので CPU ガ チャの影響は小さい https://cloud.google.com/compute/docs/cpu-platforms?hl=ja より 27
インスタンスガチャ ● そもそもクラウド上の仮想マシン(VM)は物理マシンがホスト ● n1-standard-1 における 1 は vCPU の数 である ● N1シリーズ(CPU : Skylake) を提供する物理マシンのCPU ○ インテル® Xeon® Platinum 8170M プロセッサー ○ 26コア52スレッド ● 1 個の vCPU は 1 スレッドで実現(ハイパースレッディング) ○ 1 個の物理コアで 2 個の vCPU を実現 ● つまり、物理マシン上のコアの稼働状況の影響を受けるはず ● これ以外にも、ネットワーク I/O や ネットワーク帯域、CPU、メモリの劣化 とかもありそう??? 28
インスタンスガチャ 負荷試験において インスタンスガチャが発生するのは仕方がない!!! → 複数回測定するべき どうしてもガチャが嫌ならベアメタルマシンを利用するといった 解決策もある(?) ベアメタルマシン:特定の物理サーバーをそのまま専用リソースとして利用す るコンピューティング環境 29
ルーム割り振り性能 30
client の room 割り振りで RPS が変化 32 room, 各 room に 1 client 接続 16 room, 各 room に 2 client 接続 8 room, 各 room に 4 client 接続 4 room, 各 room に 8 client 接続 1 room, 各 room に 32 client 接続 ● 同時接続人数が同じでも、room の割り振り方でRPSが変化 ○ ○ 1 room に 32 client 接続する場合は、[サーバーは1 client のリクエストを 32 client 転送] × 32 → N × N の処理なので重い 32 room で各 room 1 client 接続の場合は [サーバーは 1client のリクエス トをclientに送り返す] × 32 → N の処理なので軽い 31
dotTraceによるプロファイリング パフォーマンスのボトルネックや パフォーマンス向上の寄与原因を調査 32
プロファイリング( .NET6 と .NET9) .NET 6.0 .NET 9.0 パフォーマンス向上の 寄与要因は 何だろうか? 6896 ± 219 RPS (平均±標準偏差) 5605 ± 192 RPS (平均±標準偏差) 23 % 向上 33
プロファイリング ● dotTrace の Sampling Mode を利用 ○ https://www.jetbrains.com/help/profiler/dotTrace_Introduction.h tml ● .NET6と.NET9のプロファイルを比較 ● 単体のプロファイルでどのあたりがボトルネックかを確認 ○ csproj で最適なパラメータにあたりをつけて調整することが可能 34
プロファイリング結果 (.NET6と.NET9) 35
プロファイリング結果 (.NET6と.NET9) CPU スレッド時間:各スレッド がCPUを使って処理を実行し た合計時間 (.NET6) (.NET9) 例えば、負荷試験は 10分間 = 600,000 ms (CPU時間) で あるが、CPUスレッド時間は それ以上の値となる .NET9 の方が.NET6より CPU スレッド 時間が多い その分だけ多くの処理を行っている 36
プロファイリング結果 (.NET6と.NET9) System code : 主にThread 関係の処理、ソケット Read/Send のシステムコー ル File I/O : アプリケーションレ イヤでのストリーム読み書き Sleep : スレッドの待機時間 .NET9 の方が.NET6より ● System Code が増加 ● File I/O と Sleep が減少 つまり、Thread関係の処理や通信周り の処理が最適化された? 37
プロファイリング結果 (.NET6と.NET9) System code の中で処理時間 が増加した関数を列挙 (.NET6) (.NET9) 38
.NET のリリースノート .NET 7.0 .NET 9.0 https://learn.microsoft.com/ja-jp/dotnet/core/whats-new/dotnet-9/overvie w ● ● https://learn.microsoft.com/ja-jp/dotnet/core/whats-new/dotnet-7 .NET6 -> .NET9 の間で様々なパフォーマンス向上(特 に.NET7) .NET 6 の LTS はサポート切れなので、次の LTS の .NET 8 への更新は手軽なパフォーマンス向上に繋がる 39
同時接続人数を測定 40
実験条件 ● Platform : .NET 9.0 ● Server Spec ○ n1-standard-1, n1-highcpu-4, n1-highcpu-16 ○ CPU : Intel SkyLake ● MagicOnion6.1.5 のStremaingHub の HTPP/2 通信 (not https) ● csproj はほぼデフォルト設定 ● 10分間、各 client が server に対して約 14 ms 毎 (72 fps) で位置情報を ランダムに更新するリクエストを送信 ● CPU 使用率が 90-95 % となるまで 1 room の同時接続人数を増やす 41
n1-standard-1 同時接続 32 client で CPU 使用率 約95% 42
n1-higchcpu-4 同時接続 64 clientで CPU使用率が約95 % 43
n1-higchcpu-16 同時接続128 client で CPU使用率約90% 44
1 room の同時接続人数と必要な vCPU数 二次関数的に増加 32 人 -> vCPU 1 個 64 人 -> vCPU 4 個 128 人 -> vCPU 16個 1 インスタンスで実 現する 1 room の 同時接続数には限 界がありそうだ な..... 45
さらに同時接続人数を増やすには? ● ハードウェアのスペックアップ ○ vCPU を増やす! ■ お金の力で解決 ● ソフトウェアの工夫 ○ 自身から遠いユーザーの位置は同期しないor同期頻度を下げる ● クラウドアーキテクチャを見直す 46
ハードウェアのスペックアップ ● お金の力で vCPU を増やす! ○ ただし、同時接続人数に対して二次関数的にvCPU数が必要になるの課 金額も二次関数的に増える (vCPU数と課金額は線形) https://cloud.google.com/compute/vm-in stance-pricing?hl=ja#compute-optimized _machine_types より 47
クラウドアーキテクチャの見直し:ロードバランサ + Pub/Sub 構成 LB room a 1 room を複数のインス タンスで構成する room a room a room a https://github.com/Cysharp/AlterNats?tab=readme-ov-file#architecture-guide より 48
負荷試験の費用 49
費用 50
まとめ 51
MagicOnionパフォーマンスまとめ ● .NET6 -> NET9 の更新で 23 % パフォーマンス向上 ● n1-standard-1 (vCPU 1 個) のマシンで 最大 16369 RPS ○ 32 client が 1 client 1 room で接続し、各 client が可能 な限り高頻度でリクエストを送信 ● 1 room に 128 人の同時接続が可能 ○ n1-highcpu-16 (vCPU 16 個) のマシンを使った場合 ○ CPU 使用率が約90%基準 ○ 各 client が約 14 ms に1 回の頻度でリクエスト送信 52