MagicOnionサーバーのパフォーマンス調査と.NET更新によるパフォーマンス改善

13.7K Views

November 17, 24

スライド概要

[お題目]
・負荷試験の背景・目的
・MagicOnionの概要
・MagicOnionを利用したクラウドアーキテクチャ
・GKE・DFrameを利用した負荷試験環境の構築
・負荷試験結果・考察
  ・限界性能と .NET更新によるパフォーマンス向上
  ・インスタンスガチャの存在
  ・dotTraceによるプロファイリング
  ・同時接続人数
・負荷試験の費用

profile-image

VRコミュニケーションを支えるエンジニアをやっています

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

MagicOnionサーバー のパフォーマンス調査 と.NET更新によるパ フォーマンス改善 とうとう 1

2.

自己紹介 ● とうとう( X :@__tou__tou ) ○ VRコミュニケーションを支えるエンジニア ○ 領域:インフラ・リアルタイムサーバー ● 上級バーチャルリアリティ技術者(日本バーチャルリアリティ学会) ● VRChat でよく遊んでいます 2

3.

お題 ● ● ● ● ● 負荷試験の背景・目的 MagicOnionの概要 MagicOnionを利用したクラウドアーキテクチャ GKE・DFrameを利用した負荷試験環境の構築 負荷試験結果・考察 ○ ○ ○ ○ 限界性能と .NET更新によるパフォーマンス向上 インスタンスガチャの存在 dotTraceによるプロファイリング 同時接続人数 ● 負荷試験の費用 3

4.

背景 ● メタバース等ではユーザーの位置情報を共有するために MagicOnion等のリアルタイムサーバーを利用 ● サーバー1台で運用可能なルーム数や同時接続人数を把握す ることは「安定したユーザー体験の提供」や「サーバー料金のコ スト効率を高める」ために重要 4

5.

目的 ● 負荷試験により、MagicOnionサーバーの1台あたりの同時接 続人数を測定 ● .NET 更新によるパフォーマンス改善 5

6.

MagicOnionの概要 6

7.

MagicOnionの概要 ● .NETベースの 双方向 RPC フレームワークであり、リアルタイ ム通信を提供 ● サーバー・クライアントをともに C# で実装可能 ○ クライアントは Unity にも対応している ● 開発は Cysharp 社で MIT ライセンス ○ MagicOnion - GitHub 7

8.

MagicOnionを利用した クラウドアーキテクチャ 8

9.

シングルサーバー構成 構築は簡単だけど、サーバー数がス ケールしないので、トラフィックが増え るとボトルネックになる MagicOnionサーバーの1 プロセスは 複数の room(実装上はGroup)を持 つことができる room a room b https://github.com/Cysharp/AlterNats?tab=readme-ov-file#architecture-guide より 9

10.

サービスディスカバリ構成 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

11.

ロードバランサ + 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.

負荷試験環境の構築 12

13.

負荷試験対象:シングルサーバー構成 今回の負荷試験では、 MagicOnion サーバー 1 台あたりの性能 を評価 スケーリング性能は評価しない https://github.com/Cysharp/AlterNats?tab=readme-ov-file#architecture-guide より 13

14.

負荷試験環境 Google Kubernetes Engine : コンテナ化したアプリのデプロイ、管 理、スケーリングを担う, MagicOnionに接続するための Client を沢山用意するために利用 DFrame (Cysharp) : C# 製の負荷試験フレームワーク, C#で負荷シナリオを記述できるので 自由度が高い,Unityでも利用できる (が今回は通常の.NET版を利用) 14 Google Kubernetes Engine を使用したロード バランシング テスト を参考に構築

15.

負荷試験環境 WebUI を提供 相当 15

16.

MagicOnionサーバーのデプロイフロー 16

17.

負荷試験環境のデプロイフロー 17

18.

負荷試験結果 18

19.

ストレステスト サーバーの限界性能を評価 19

20.

実験条件 ● 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

21.

結果の 一 例 1 client の結果 Latencyの統計値と RPS (Request Per Second) 32 client 合計の 秒間リクエスト数 21

22.

.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

23.

ストレステストにおける注意事項 ● worker( client )の計算リソースが十分であるか ○ 不足していると、サーバーに十分な負荷がかからない ● サーバーCPUに十分負荷がかかっているか ● インスタンスガチャ ○ CPUを指定しない場合、インスタンス性能バラつきが大きくな る ● メモリが十分か ● ネットワーク帯域が十分か 23

24.

client の計算リソースが十分か VMインスタンス上で複数 の client が稼働 CPU 使用率 80% 未満な ので計算リソースは十分 ≒ サーバーに十分な負荷が かけられている 24

25.

サーバー CPUに対する十分な負荷 CPU 使用率が 100 % に 張り付いている ≒ 十分な負荷 25

26.

インスタンスガチャ ストレステストの結果 (MagicOnion on .NET 9.0) 同実験条件であるはずだ が、結果にバラつきがある ????? 6896 ± 219 RPS (平均±標準偏差) インスタンスの性能に バラつきがある? → インスタンスガチャ 26

27.

インスタンスガチャ ● 本実験で利用したマシンタイプは n1-standard-1 ● N1 はデフォルトで以下のいずれかの CPU が割り当てられる CPUの周波数が異なれば パフォーマンスに影響 ただし、本実験では CPUを 指定してインスタンスを作 成しているので CPU ガ チャの影響は小さい https://cloud.google.com/compute/docs/cpu-platforms?hl=ja より 27

28.

インスタンスガチャ ● そもそもクラウド上の仮想マシン(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.

インスタンスガチャ 負荷試験において インスタンスガチャが発生するのは仕方がない!!! → 複数回測定するべき どうしてもガチャが嫌ならベアメタルマシンを利用するといった 解決策もある(?) ベアメタルマシン:特定の物理サーバーをそのまま専用リソースとして利用す るコンピューティング環境 29

30.

ルーム割り振り性能 30

31.

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

32.

dotTraceによるプロファイリング パフォーマンスのボトルネックや パフォーマンス向上の寄与原因を調査 32

33.

プロファイリング( .NET6 と .NET9) .NET 6.0 .NET 9.0 パフォーマンス向上の 寄与要因は 何だろうか? 6896 ± 219 RPS (平均±標準偏差) 5605 ± 192 RPS (平均±標準偏差) 23 % 向上 33

34.

プロファイリング ● dotTrace の Sampling Mode を利用 ○ https://www.jetbrains.com/help/profiler/dotTrace_Introduction.h tml ● .NET6と.NET9のプロファイルを比較 ● 単体のプロファイルでどのあたりがボトルネックかを確認 ○ csproj で最適なパラメータにあたりをつけて調整することが可能 34

35.

プロファイリング結果 (.NET6と.NET9) 35

36.

プロファイリング結果 (.NET6と.NET9) CPU スレッド時間:各スレッド がCPUを使って処理を実行し た合計時間 (.NET6) (.NET9) 例えば、負荷試験は 10分間 = 600,000 ms (CPU時間) で あるが、CPUスレッド時間は それ以上の値となる .NET9 の方が.NET6より CPU スレッド 時間が多い その分だけ多くの処理を行っている 36

37.

プロファイリング結果 (.NET6と.NET9) System code : 主にThread 関係の処理、ソケット Read/Send のシステムコー ル File I/O : アプリケーションレ イヤでのストリーム読み書き Sleep : スレッドの待機時間 .NET9 の方が.NET6より ● System Code が増加 ● File I/O と Sleep が減少 つまり、Thread関係の処理や通信周り の処理が最適化された? 37

38.

プロファイリング結果 (.NET6と.NET9) System code の中で処理時間 が増加した関数を列挙 (.NET6) (.NET9) 38

39.

.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.

同時接続人数を測定 40

41.

実験条件 ● 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

42.

n1-standard-1 同時接続 32 client で CPU 使用率 約95% 42

43.

n1-higchcpu-4 同時接続 64 clientで CPU使用率が約95 % 43

44.

n1-higchcpu-16 同時接続128 client で CPU使用率約90% 44

45.

1 room の同時接続人数と必要な vCPU数 二次関数的に増加 32 人 -> vCPU 1 個 64 人 -> vCPU 4 個 128 人 -> vCPU 16個 1 インスタンスで実 現する 1 room の 同時接続数には限 界がありそうだ な..... 45

46.

さらに同時接続人数を増やすには? ● ハードウェアのスペックアップ ○ vCPU を増やす! ■ お金の力で解決 ● ソフトウェアの工夫 ○ 自身から遠いユーザーの位置は同期しないor同期頻度を下げる ● クラウドアーキテクチャを見直す 46

47.

ハードウェアのスペックアップ ● お金の力で vCPU を増やす! ○ ただし、同時接続人数に対して二次関数的にvCPU数が必要になるの課 金額も二次関数的に増える (vCPU数と課金額は線形) https://cloud.google.com/compute/vm-in stance-pricing?hl=ja#compute-optimized _machine_types より 47

48.

クラウドアーキテクチャの見直し:ロードバランサ + 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.

負荷試験の費用 49

50.

費用 50

51.

まとめ 51

52.

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