iperf を利用して SORACOM IoT SIM の通信速度を計測して時系列に可視化してみた

## はじめに
こちらは [SORACOM Advent Calendar 2023](https://qiita.com/advent-calendar/2023/soracom) 8 日目の記事です。スマートフォンなどで利用されるセルラー通信では利用している基地局の混雑度合いなどで通信速度が大きく変動すると言われていますが、実際にどのくらい変わるのか知りたくなって調べてみました。

## 通信速度の計測

端末からサーバに対して、単位時間あたりに転送したデータ量 (ネットワーク帯域幅) を計測します。単位は bps (bits per second) です。なお、この記事中では「通信速度」=「ネットワーク帯域幅」として記載しています。

今回は iperf というネットワークパフォーマンスを測定できるツールを用いました。
また、SORACOM IoT SIM の plan-D D-300MB というサブスクリプションプランで検証しました。

## 通信速度のボトルネック (セルラー通信)

セルラー通信をする際には以下のような要因で速度が低下することがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556409/f7a1862d-bb7c-7e36-7be3-3c3ee6026fdf.png)

1. 端末周辺の電波環境の悪化
2. キャリアの基地局のキャパシティ不足
3. キャリアのコアネットワークの帯域不足
4. (MVNO を利用している場合) キャリアと MVNO (今回であれば SORACOM) 間の回線の帯域不足
5. (MVNO を利用している場合) MVNO (今回であれば SORACOM) 内の設備のキャパシティ不足
6. MVNO から接続先のサーバ間の回線の帯域不足
7. サーバのキャパシティ不足

見ていただけると分かるように、ユーザー側でコントロール可能な要素がほぼありません。苦笑
強いていうならば、「1. 端末の電波環境」くらいでしょうか。でもこれにしても場所が移動できる場合に限られますね。

とはいえ、セルラー通信の速度は様々な要因で変化し得るものであるという認識を持っておくことは重要です。
上記の要因は時事刻々と変化するものであるため、定期的に通信速度を計測して 24 時間分を時系列で可視化してみることにしました。

### SORACOM IoT SIM の速度クラス

上述したとおり、今回は SORACOM IoT SIM の plan-D D-300MB というサブスクリプションプランで検証しました
SORACOM IoT SIM には速度クラスという機能があり、SORACOM 設備内を通過する際の通信速度の上限を設定することができます。今回は s1.4xfast (8 Mbps が上限) に設定して検証しました。

## 今回の構成

今回は以下のような構成をとっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556409/dc0861d5-3fe6-9801-d57f-286421bd3c50.png)

デバイス (Raspberry Pi) は基地局・交換局を経由して、SORACOM に到達します。その先は、SORACOM Canal という VPC ピアリング接続ができるサービスを利用して、AWS に構築した iperf サーバへ接続して通信速度を取得します。
今回は AWS EC2 上に専用の iperf サーバを構築したため、上記の「7. サーバのキャパシティ不足」による影響は限定的だと思います。

さらに、取得した通信速度をデバイスから SORACOM Harvest Data に送信して、SORACOM Lagoon で可視化します。

## 計測

上述したように、今回は iperf を利用して通信速度 (ネットワーク帯域幅) を計測しました。サーバ (EC2) 、クライアント (Raspberry Pi) それぞれに iperf をインストールしてから以下を実行します。

サーバ側は以下のように `-D` オプションを付けて、デーモンとしてバックグラウンドで動作させます。

```
[ec2-user@ip-10-0-0-12 ~]$ iperf3 -s -D
[ec2-user@ip-10-0-0-12 ~]$ 
```
クライアント側でコマンドを実行してみます。なお、10.0.0.12 は iperf サーバ (EC2) の IP アドレスです。

```
pi@raspberrypi:~ $ iperf3 -c 10.0.0.12 -O 5
Connecting to host 10.0.0.12, port 5201
[  5] local 192.168.1.200 port 44680 connected to 10.0.0.12 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   716 KBytes  5.87 Mbits/sec    0   58.3 KBytes       (omitted)
[  5]   1.00-2.00   sec   720 KBytes  5.90 Mbits/sec    4   24.6 KBytes       (omitted)
[  5]   2.00-3.00   sec   127 KBytes  1.04 Mbits/sec    6   7.77 KBytes       (omitted)
[  5]   3.00-4.00   sec   127 KBytes  1.04 Mbits/sec    0   15.5 KBytes       (omitted)
[  5]   4.00-5.00   sec   381 KBytes  3.12 Mbits/sec    0   25.9 KBytes       (omitted)
[  5]   0.00-1.00   sec   508 KBytes  4.16 Mbits/sec    0   37.6 KBytes       
[  5]   1.00-2.00   sec   635 KBytes  5.20 Mbits/sec    0   47.9 KBytes       
[  5]   2.00-3.00   sec   635 KBytes  5.20 Mbits/sec    0   57.0 KBytes       
[  5]   3.00-4.00   sec   635 KBytes  5.20 Mbits/sec    0   64.7 KBytes       
[  5]   4.00-5.00   sec   768 KBytes  6.29 Mbits/sec    0   94.5 KBytes       
[  5]   5.00-6.00   sec   825 KBytes  6.76 Mbits/sec    0    148 KBytes       
[  5]   6.00-7.00   sec   698 KBytes  5.72 Mbits/sec    0    215 KBytes       
[  5]   7.00-8.00   sec  1015 KBytes  8.32 Mbits/sec    0    300 KBytes       
[  5]   8.00-9.00   sec   952 KBytes  7.80 Mbits/sec    0    409 KBytes       
[  5]   9.00-10.00  sec   571 KBytes  4.68 Mbits/sec   18    471 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  7.07 MBytes  5.93 Mbits/sec   18             sender
[  5]   0.00-10.60  sec  6.31 MBytes  4.99 Mbits/sec                  receiver

iperf Done.
```

`-O` オプションをつけることで、計測開始直後から指定した秒数を集計対象から除外できます。
iperf はデフォルトでは TCP でネットワークパフォーマンスを計測するのですが、おそらく TCP コネクション確立の影響で計測開始直後は通信速度が低下する場合があります。今回は少し余裕をもって、計測開始直後の 5 秒間は集計対象外としました。

さらに、`-J` オプションにより、結果を JSON 形式で出力できます。
今回は以下のコマンド実行することで通信速度の平均値を取得しました。

```
pi@raspberrypi:~ $ iperf3 -c 10.0.0.12 -O 5 -J | jq '.end.sum_sent.bits_per_second'
5041564.958421443
```
上記では通信速度が 5041564.958421443 bps (5.04 Mbps) と計測されています。

通信速度の取得に加えて、curl で SORACOM Harvest Data へ結果を送信する簡単なスクリプトを作成し、cron で定期実行しました。

## 結果

定期取得した通信速度を時系列で可視化した結果が以下です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556409/a89362f9-ea8c-9a47-8e0b-9e497edf04b0.png)

上述したように速度クラスで通信速度上限を 8 Mbps にしているので、8 Mbps を超過することはありません。
AM 3 〜 5 時は相対的に通信速度が上がっていますね。この時間帯は基地局へのリクエストが少なくキャパシティに余裕があるからでしょうか。
一方、お昼過ぎの 14 〜 15 時は 3,4 Mbps まで通信速度が落ち込んでいます。

ちなみに、自前でサーバを構築しなくても、公開されている iperf サーバを利用することもできます。
試しに、[こちらのページ](https://iperf.fr/iperf-servers.php) から一つ選んで計測してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556409/ab7a35a8-2b85-f370-e1e8-ac06bde224d1.png)

自前で構築した iperf サーバ (緑色) と並べて表示させると以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556409/74ffac67-cae9-0696-d586-909214b33d1f.png)

両者の差分は以下のような点になります。

 - MVNO から接続先のサーバ間の回線
 - サーバスペックや他リクエストの影響

いずれも自前のサーバの方が有利な気がしますが、明確な差は出ていないように見えます。
ただ、公開されている iperf サーバではタイミングによって通信速度が計測できないことがありました。一定以上の負荷上昇があった場合は、リクエストを拒否しているのかもしれません。(想像ですが)

## まとめ

いかがでしたでしょうか。時間帯によって通信速度が大きく変動することが分かりました。
なお、今回は平日に自宅 (神奈川県) で計測をしたのですが、おそらく土日祝日や都心部で計測するとまた違った傾向が出るのだと思います。

特にネットワークカメラのように容量の大きなデータをセルラー通信で転送する場合などはこういった変動を考慮に入れて使用することが大事だと思いました。

みなさまももし興味があれば計測してみてください！
ではでは！