---
title: MagicOnionサーバーのパフォーマンス調査と.NET更新によるパフォーマンス改善
tags:  #magiconion #.net #dotnet  
author: [toutou node](https://convert.docswell.com/user/toutou)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/PJRM25V5E9.jpg?width=480
description: [お題目] ・負荷試験の背景・目的 ・MagicOnionの概要 ・MagicOnionを利用したクラウドアーキテクチャ ・GKE・DFrameを利用した負荷試験環境の構築 ・負荷試験結果・考察 　　・限界性能と .NET更新によるパフォーマンス向上 　　・インスタンスガチャの存在 　　・dotTraceによるプロファイリング 　　・同時接続人数 ・負荷試験の費用
published: November 17, 24
canonical: https://convert.docswell.com/s/toutou/Z7RJLD-2024-11-17-155150
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/PJRM25V5E9.jpg)

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


# Page. 2

![Page Image](https://bcdn.docswell.com/page/PEXVDKZX7X.jpg)

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


# Page. 3

![Page Image](https://bcdn.docswell.com/page/3EKQX589ED.jpg)

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


# Page. 4

![Page Image](https://bcdn.docswell.com/page/L73P5K29E5.jpg)

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


# Page. 5

![Page Image](https://bcdn.docswell.com/page/87DLD3Z8EG.jpg)

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


# Page. 6

![Page Image](https://bcdn.docswell.com/page/VJP2X4DWJ8.jpg)

MagicOnionの概要
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/2EVDLX19EQ.jpg)

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


# Page. 8

![Page Image](https://bcdn.docswell.com/page/57GYXV247L.jpg)

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


# Page. 9

![Page Image](https://bcdn.docswell.com/page/4EQM86PRJP.jpg)

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


# Page. 10

![Page Image](https://bcdn.docswell.com/page/KJ4V24YQE1.jpg)

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


# Page. 11

![Page Image](https://bcdn.docswell.com/page/LE13M46LJG.jpg)

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


# Page. 12

![Page Image](https://bcdn.docswell.com/page/GEWP3XWQJ2.jpg)

負荷試験環境の構築
12


# Page. 13

![Page Image](https://bcdn.docswell.com/page/47ZKV65373.jpg)

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


# Page. 14

![Page Image](https://bcdn.docswell.com/page/YJ6Q529ZJV.jpg)

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


# Page. 15

![Page Image](https://bcdn.docswell.com/page/GJ5RY2N974.jpg)

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


# Page. 16

![Page Image](https://bcdn.docswell.com/page/LE3P5K22J5.jpg)

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


# Page. 17

![Page Image](https://bcdn.docswell.com/page/8EDLD3Z6JG.jpg)

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


# Page. 18

![Page Image](https://bcdn.docswell.com/page/V7P2X4YZ78.jpg)

負荷試験結果
18


# Page. 19

![Page Image](https://bcdn.docswell.com/page/2JVDLXGMJQ.jpg)

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


# Page. 20

![Page Image](https://bcdn.docswell.com/page/5EGYXV8XEL.jpg)

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


# Page. 21

![Page Image](https://bcdn.docswell.com/page/4JQM86957P.jpg)

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


# Page. 22

![Page Image](https://bcdn.docswell.com/page/K74V24XVJ1.jpg)

.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


# Page. 23

![Page Image](https://bcdn.docswell.com/page/LJ13M4N47G.jpg)

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


# Page. 24

![Page Image](https://bcdn.docswell.com/page/GJWP3X4Z72.jpg)

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


# Page. 25

![Page Image](https://bcdn.docswell.com/page/4EZKV62LE3.jpg)

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


# Page. 26

![Page Image](https://bcdn.docswell.com/page/Y76Q52VM7V.jpg)

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


# Page. 27

![Page Image](https://bcdn.docswell.com/page/G75RY2DQE4.jpg)

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


# Page. 28

![Page Image](https://bcdn.docswell.com/page/9J2DG48WJR.jpg)

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


# Page. 29

![Page Image](https://bcdn.docswell.com/page/DEY2VM69EM.jpg)

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


# Page. 30

![Page Image](https://bcdn.docswell.com/page/VJN8MWZD78.jpg)

ルーム割り振り性能
30


# Page. 31

![Page Image](https://bcdn.docswell.com/page/YE9KNXZ8E3.jpg)

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


# Page. 32

![Page Image](https://bcdn.docswell.com/page/GE8RK21ZJD.jpg)

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


# Page. 33

![Page Image](https://bcdn.docswell.com/page/LELKZ2Q1JR.jpg)

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


# Page. 34

![Page Image](https://bcdn.docswell.com/page/4JM2V815JW.jpg)

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


# Page. 35

![Page Image](https://bcdn.docswell.com/page/PJRM25LZE9.jpg)

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


# Page. 36

![Page Image](https://bcdn.docswell.com/page/PEXVDKW17X.jpg)

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


# Page. 37

![Page Image](https://bcdn.docswell.com/page/3EKQX5VMED.jpg)

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


# Page. 38

![Page Image](https://bcdn.docswell.com/page/L73P5KM2E5.jpg)

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


# Page. 39

![Page Image](https://bcdn.docswell.com/page/87DLD366EG.jpg)

.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 -&gt; .NET9 の間で様々なパフォーマンス向上（特
に.NET7）
.NET 6 の LTS はサポート切れなので、次の LTS の .NET 8
への更新は手軽なパフォーマンス向上に繋がる
39


# Page. 40

![Page Image](https://bcdn.docswell.com/page/VJP2XPZZJ8.jpg)

同時接続人数を測定
40


# Page. 41

![Page Image](https://bcdn.docswell.com/page/2EVDL2WMEQ.jpg)

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


# Page. 42

![Page Image](https://bcdn.docswell.com/page/57GYXRDX7L.jpg)

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


# Page. 43

![Page Image](https://bcdn.docswell.com/page/4EQM8V15JP.jpg)

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


# Page. 44

![Page Image](https://bcdn.docswell.com/page/KJ4V2MRVE1.jpg)

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


# Page. 45

![Page Image](https://bcdn.docswell.com/page/LE13M8Q4JG.jpg)

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


# Page. 46

![Page Image](https://bcdn.docswell.com/page/GEWP3ZMZJ2.jpg)

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


# Page. 47

![Page Image](https://bcdn.docswell.com/page/47ZKV1QL73.jpg)

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


# Page. 48

![Page Image](https://bcdn.docswell.com/page/YJ6Q5L6MJV.jpg)

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


# Page. 49

![Page Image](https://bcdn.docswell.com/page/GJ5RY16Q74.jpg)

負荷試験の費用
49


# Page. 50

![Page Image](https://bcdn.docswell.com/page/9E2DG1MWER.jpg)

費用
50


# Page. 51

![Page Image](https://bcdn.docswell.com/page/D7Y2VZX97M.jpg)

まとめ
51


# Page. 52

![Page Image](https://bcdn.docswell.com/page/VEN8M31DJ8.jpg)

MagicOnionパフォーマンスまとめ
● .NET6 -&gt; 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


