この記事はシスコ社員有志による Cisco Systems Japan Advent Calendar 2021 🎁 2枚目の 13日目として投稿しています。
2021年1枚目: https://qiita.com/advent-calendar/2021/cisco
2021年2枚目: https://qiita.com/advent-calendar/2021/cisco2
はじめに
前回は、標準的なベンチマークツールを使って、ラズパイや Macと Cisco IOxプラットフォームを比較してみました。
今回は、Cisco IOxの性能を決めるリソースプロファイルの CPUユニットについて深堀りしてみたいと思います。
IOxプラットフォーム代表は、前回と同様に Cisco Catalyst IR1101です。
略称 | HW | CPU | IOx用メモリ | OS |
---|---|---|---|---|
IR1101 | Catalyst IR1101 Rugged Series Router | ARMv8 4-Core 600MHz | 862MB | IOS-XE 17.3.4 |
IOxアプリは前回の測定に使った sysbenchを Dockerタイプで動かします。測定方法も同様です。特に断りがなければ、sysbenchを連続で20回動かします。EPSは 10000までの素数の計算を1秒間に何回実行できたかを表します。詳細は前回の sysbenchの測定を参照してください。
CPUユニット値の総数
はじめに コンテナ1つをCPUユニット値を変えて 動かしてみました。
ID | Unit | EPS | 処理時間 |
---|---|---|---|
1 | 1 | 1155.49 | 200.264701 |
2 | 2 | 1152.15 | 200.272761 |
3 | 4 | 1153.94 | 200.256042 |
4 | 8 | 1155.03 | 200.260993 |
5 | 16 | 1158.40 | 200.258344 |
6 | 32 | 1157.52 | 200.256584 |
7 | 64 | 1154.19 | 200.260360 |
8 | 128 | 1158.23 | 200.261504 |
9 | 256 | 1156.87 | 200.267493 |
10 | 512 | 1158.54 | 200.259878 |
11 | 1024 | 1157.52 | 200.276326 |
12 | 1155 | 1156.81 | 200.263486 |
平均 | 200.263206 |
CPUユニット値を変えても EPSや処理時間に極端な差は見られません。
CPUユニットは最低限確保される量であり、空きがあればそれより多くの量が割り当てられる。
とありますので、コンテナが1つの場合は、CPUユニット値とは関係なくリソースの空きが割り当てられたため、ほぼ同じ性能が出たと考えられます。
次に、CPUユニット値 64のコンテナを 20個 動かして、sysbenchを同時に動かしてみます。
総ユニット数は 1280です。Platform Support Matrixの CPUユニット値 1255や、IOx Local Manager1の画面に表示される Exclusive CPUユニット値 1155よりも大きな値になっています。
ここで同時とは、予めコンテナを Activateして Startさせておき、指定時刻になったらsysbenchを起動させます。コンテナが起動する時刻は異なりますが、ほぼ同時にsysbenchが走ることになります。これは、他のコンテナや sysbenchが動いている場合とそうでない場合とではEPSや処理時間に影響が出るためです。ここは後述します。
さて、結果は、
ID | Unit | 回数 | EPS | 開始時刻 | 終了時刻 | 処理時間 |
---|---|---|---|---|---|---|
1 | 64 | 20 | 97.80 | 01:40:00 | 01:43:23 | 202.770128 |
2 | 64 | 20 | 98.03 | 01:40:00 | 01:43:23 | 202.603824 |
3 | 64 | 20 | 96.82 | 01:40:00 | 01:43:23 | 202.734949 |
4 | 64 | 20 | 96.91 | 01:40:00 | 01:43:23 | 202.766551 |
5 | 64 | 20 | 97.32 | 01:40:00 | 01:43:23 | 202.741718 |
6 | 64 | 20 | 97.74 | 01:40:00 | 01:43:22 | 202.419813 |
7 | 64 | 20 | 97.97 | 01:40:00 | 01:43:23 | 202.707566 |
8 | 64 | 20 | 98.01 | 01:40:00 | 01:43:23 | 202.316338 |
9 | 64 | 20 | 97.28 | 01:40:00 | 01:43:23 | 202.603302 |
10 | 64 | 20 | 98.21 | 01:40:00 | 01:43:23 | 202.723129 |
11 | 64 | 20 | 97.87 | 01:40:01 | 01:43:23 | 202.15009 |
12 | 64 | 20 | 97.60 | 01:40:00 | 01:43:23 | 202.733976 |
13 | 64 | 20 | 97.07 | 01:40:00 | 01:43:23 | 202.794183 |
14 | 64 | 20 | 97.09 | 01:40:00 | 01:43:23 | 202.830263 |
15 | 64 | 20 | 98.49 | 01:40:00 | 01:43:23 | 202.548262 |
16 | 64 | 20 | 97.64 | 01:40:01 | 01:43:23 | 202.177262 |
17 | 64 | 20 | 97.31 | 01:40:00 | 01:43:23 | 202.688429 |
18 | 64 | 20 | 98.04 | 01:40:00 | 01:43:22 | 202.428391 |
19 | 64 | 20 | 98.47 | 01:40:00 | 01:43:23 | 202.661294 |
20 | 64 | 20 | 98.16 | 01:40:00 | 01:43:23 | 202.547466 |
処理時間:
平均値: 202.5973467
中央値: 202.770128
最小値: 202.15009
最大値: 202.830263
エラーもなく動きました。起動時間もほぼそろっています。EPSは単独で動かした時(1154.19)の約12分の1程度になっています。
この測定では総CPUユニット数が 1280でした。この事から、Platform Support Matrixや IOx Local Managerに表記されているCPUユニット値は、全てのコンテナに割り当てたCPUユニット値の総数を意味する数字ではないことがわかります2。
さて、Platform Support Matrixでは、IR1101 (IOS XE 17.2.1)の CPUユニット値は 1255となっています。一方、IR1101の IOx Local Managerでは、CPUユニットの Exclusiveの値は 1155になっていました。IR1101で IOxアプリを Activateする時に CPUユニット値を 1255にすると下記のエラーになります。したがって、少なくとも IR1101 IOS-XE 17.3.4では、設定できるCPUユニットの最大値は 1155のようです。
Error. Server returned 500
{
"description": "App Activation error: Platform does not have enough cpu resource, available cpu 1155",
"errorcode": -1021,
"message": "Error while changing app state"
}
Activating Profile ir1101@tlab
今度は CPUユニット値 1155でコンテナを20個 動かしてみましょう。
ID | Unit | 回数 | EPS | 開始時刻 | 終了時刻 | 処理時間 |
---|---|---|---|---|---|---|
1 | 1155 | 20 | 93.27 | 16:30:00 | 16:33:25 | 204.462671 |
2 | 1155 | 20 | 92.34 | 16:30:00 | 16:33:29 | 209.033972 |
3 | 1155 | 20 | 93.67 | 16:30:00 | 16:33:26 | 205.33544 |
4 | 1155 | 20 | 92.88 | 16:30:00 | 16:33:28 | 208.045846 |
5 | 1155 | 20 | 93.76 | 16:30:00 | 16:33:27 | 206.868771 |
6 | 1155 | 20 | 94.93 | 16:30:00 | 16:33:25 | 205.364254 |
7 | 1155 | 20 | 102.68 | 16:30:00 | 16:33:32 | 211.466148 |
8 | 1155 | 20 | 93.21 | 16:30:00 | 16:33:22 | 202.202063 |
9 | 1155 | 20 | 91.01 | 16:30:00 | 16:33:28 | 207.95003 |
10 | 1155 | 20 | 90.34 | 16:30:00 | 16:33:25 | 205.586735 |
11 | 1155 | 20 | 96.66 | 16:30:00 | 16:33:30 | 209.947379 |
12 | 1155 | 20 | 90.47 | 16:30:00 | 16:33:24 | 204.575375 |
13 | 1155 | 20 | 94.83 | 16:30:00 | 16:33:25 | 204.955135 |
14 | 1155 | 20 | 93.44 | 16:30:00 | 16:33:28 | 207.529231 |
15 | 1155 | 20 | 93.52 | 16:30:00 | 16:33:28 | 207.442116 |
16 | 1155 | 20 | 92.81 | 16:30:00 | 16:33:29 | 208.548436 |
17 | 1155 | 20 | 96.29 | 16:30:00 | 16:33:25 | 204.854328 |
18 | 1155 | 20 | 90.15 | 16:30:00 | 16:33:27 | 206.460976 |
19 | 1155 | 20 | 96.07 | 16:30:00 | 16:33:30 | 209.766943 |
20 | 1155 | 20 | 94.01 | 16:30:00 | 16:33:27 | 206.551611 |
処理時間:
平均値: 206.847373
中央値: 204.462671
最小値: 202.202063
最大値: 211.466148
エラーもなく動きました。ただし、今度はEPSと処理時間にだいぶバラツキが見られます。そして処理時間の平均値が4秒程度増えています。これはどういうことでしょうか?
CPUユニット値と処理待ち時間
sysbenchの測定時間は1回10秒ですが、測定のための準備処理時間と終了処理時間があるので、1回の処理時間は10秒をわずかに超えます。macでさえ同様の測定を行うと 1回の処理時間は 10.01469955秒となりました。これはアプリの作りによるもので回避できない時間です。ここでは、この時間をオーバーヘッドと呼びます。
前述のコンテナを 1つで sysbenchを動かした時の処理時間の平均は 200.263206秒なので、1回の sysbenchに 10.013160秒かかったことになります。Macと比較するとほぼ同値3なので理想的な値と考えてよいかと思います。よって、ここでは オーバーヘッドの理想値を 0.013160秒とします。
前述のコンテナを 20個動かして、それぞれで sysbenchを動かした時の処理時間の平均は 202.597347秒でした。これは1回の sysbenchに 10.129867秒かかったことになり、オーバーヘッドは 0.129867秒になります。 理想値と比べると 0.116707秒多くなっています。
この増えた時間は何でしょうか?
OSという視点で見ると、各々の処理は短い時間で分割されて他の処理と合わせて順番に動いています。複数の処理が動く場合、OSが各処理を順番に動かすことになるので、自分の番が来るまでの待ち時間が発生します。macでも、sysbenchを 8つ同時に動かすと待ち時間は約7ミリ秒程度増えました。実際は、オーバーヘッドの時間にも待ち時間は含まれますが話を簡単にするためにここではまとめてオーバーヘッドと呼ばせて下さい。
待ち時間をどれだけ重要視するかはアプリ次第です。処理が終わりさえすればよいのであれば、数百ミリ程度の待ち時間でさえも気にしなくてよい場合があります。そして、待ち時間を少なくしたい場合はコンテナの数を減らすしかありません。
次の表では、CPUユニット値を64に固定して、コンテナの数を変えて sysbenchの処理時間を測定し、オーバーヘッドを 0.013160秒とした時の総待ち時間の平均を算出してみました。
コンテナ数 | 平均EPS | 平均処理時間 | 平均総待ち時間 |
---|---|---|---|
1 | 1154.19 | 10.013018 | -0.000142 |
2 | 1021.74 | 10.015174 | 0.002013 |
3 | 666.63 | 10.021281 | 0.008121 |
4 | 500.08 | 10.024509 | 0.011349 |
5 | 390.91 | 10.028914 | 0.015753 |
6 | 325.56 | 10.031864 | 0.018704 |
8 | 251.94 | 10.045914 | 0.032754 |
10 | 202.68 | 10.056489 | 0.043329 |
このグラフから、仮に総待ち時間を20ミリ秒程度に抑えたいとすれば、コンテナは6つまで動かせることになります。
では、CPUユニット値は待ち時間と関係するのでしょうか?
今度は同じCPUユニット値のコンテナを4つ動かして、それぞれのコンテナで sysbenchを 100回連続して動かします。そして、それが終わったら次のCPUユニット値に変えてまた同じ測定をします。CPUユニット値は 64, 128, 256, 512, 1024と変えて測定しました。さらに、コンテナ数を 8にして、同じ測定をやってみました。
この2つのグラフは、各CPUユニットの処理時間に対するヒストグラムになっています。例えば、最初のグラフでCPUユニットが64の場合は、全てのコンテナの100回全ての処理時間が10秒から10.1秒に収まっています。また、CPUユニット値が1024の場合は、多くは10秒から10.05秒の間に分布していますが、10.3秒の方までバラついています。さらに、次のグラフはコンテナ数が8ですが、CPUユニット値が1024の場合は、11秒近くまでバラツキが見られます。
これらを見るとCPUユニット値が増えると、またコンテナ数が増えるとバラツキが出るようです。そして、バラツキが出るとともに処理時間が増える事がわかります。
前述のCPUユニット値 1155でコンテナを20個動かした時に EPSと処理時間にバラツキが出たのは、待ち時間にバラツキが出たからと言えます。
CPUユニット値とCPUリソース
では、CPUユニット値が異なるコンテナを複数同時に動かすとどうなるでしょうか?
コンテナ数を 5, 6, 7と変えてみて、下記の3つのパターンで動かしてみました。
パターン | コンテナ数 | 個々のCPUユニット値 | 総CPUユニット値 |
---|---|---|---|
1 | 5 | 16,16,32,64,128 | 256 |
2 | 6 | 16,16,32,64,128,256 | 512 |
3 | 7 | 16,16,32,64,128,256,512 | 1024 |
パターン1: コンテナ数 5 の結果
ID | CPUユニット数 | EPS | 処理時間(秒) |
---|---|---|---|
1 | 16 | 130.61 | 201.993250 |
2 | 16 | 133.09 | 202.082445 |
3 | 32 | 256.35 | 201.003944 |
4 | 64 | 510.75 | 200.588916 |
5 | 128 | 1030.06 | 200.362681 |
パターン2: コンテナ数 6 の結果の結果
ID | CPUユニット数 | EPS | 処理時間(秒) |
---|---|---|---|
1 | 16 | 77.69 | 204.054772 |
2 | 16 | 76.17 | 204.007414 |
3 | 32 | 131.12 | 201.784430 |
4 | 64 | 256.60 | 200.963020 |
5 | 128 | 511.84 | 200.494939 |
6 | 256 | 1005.16 | 200.461410 |
パターン3: コンテナ数 7 の結果の結果
ID | CPUユニット数 | EPS | 処理時間(秒) |
---|---|---|---|
1 | 16 | 56.75 | 208.337649 |
2 | 16 | 55.07 | 207.749148 |
3 | 32 | 76.06 | 203.705077 |
4 | 64 | 129.24 | 201.503494 |
5 | 128 | 256.17 | 201.142755 |
6 | 256 | 511.55 | 200.602944 |
7 | 512 | 1001.72 | 200.498620 |
どのパターンも、CPUユニット値に比例してEPSがほぼ倍になっています。興味深いことに、例えばコンテナ数 5のCPUユニット値 32と、コンテナ数 6の CPUユニット値 64と、コンテナ数 7の CPUユニット値 128の EPSがほぼ同じ値になっています。コンテナの数と各CPUユニット値の比に強い関係があると言えます。大雑把には以下の関係が見えてきます。
$ EPS = 256 \cdot (\frac{1}{2})^C \cdot U $
(C: コンテナ数, U: CPUユニット数)
また、処理時間も若干ばらつきがありますが、CPUユニット値に反比例して半分になっていくように見えます。さらに、こちらも同様にコンテナの数とCPUユニット値に関係があるように見えます。
2つのグラフから、CPUリソースをCPUユニット値の比で分割して各コンテナに割りてていると考えられます。
CPUユニット値とコンテナの優先度
10個のコンテナのCPUユニット値をそれぞれ、1, 2, 4, 8, 16, 32, 64, 128, 256, 512 として、同時に動かしてみます。
ID | Unit | 回数 | EPS | 開始時刻 | 終了時刻 | 処理時間 |
---|---|---|---|---|---|---|
1 | 1 | 20 | 327.26 | 00:30:00 | 00:34:51 | 291.836666 |
2 | 2 | 20 | 219.31 | 00:30:06 | 00:34:24 | 257.887582 |
3 | 4 | 20 | 120.64 | 00:30:02 | 00:33:56 | 233.717882 |
4 | 8 | 20 | 79.38 | 00:30:01 | 00:33:40 | 219.2109 |
5 | 16 | 20 | 69.61 | 00:30:00 | 00:33:30 | 209.695999 |
6 | 32 | 20 | 73.25 | 00:30:00 | 00:33:23 | 203.491301 |
7 | 64 | 20 | 134.42 | 00:30:00 | 00:33:22 | 201.868421 |
8 | 128 | 20 | 260.40 | 00:30:00 | 00:33:20 | 200.836072 |
9 | 256 | 20 | 515.35 | 00:30:00 | 00:33:20 | 200.450724 |
10 | 512 | 20 | 1001.11 | 00:30:00 | 00:33:20 | 200.466724 |
CPUユニット値 1, 2, 4, 8の EPSが 16より上回っています。そして、CPUユニット値の小さい方が処理時間がより多くかかっています。
個々の sysbenchの開始時間がどうなっているかプロットしてみました。1つの点が各コンテナでの各sysbenchの開始時間になります。
このグラフから、CPUユニット値の大きなコンテナの処理が 200秒付近で終わってしまったため、その分CPUリソースが CPUユニット値の小さなコンテナに割り当てられたため、CPUユニット値 1, 2, 4, 8の方が 16より EPSがうわ待った原因と考えられます。3回やってほぼ同じ状況でした。IOxアプリを Activate4した時間が関係しないか念の為に逆順に Activateしても同じでした。
また、CPUユニット数はコンテナの優先度を示していると予想できそうです。そして、大きければより多くの実行機会が割り当てられていると言えそうです。
一方で、複数のコンテナを同時に動かす場合、CPUユニット値の最大値と最小値の幅が大きいと小さい方の待ち時間が増えて結果的に処理時間が増える事がわかりました。
こうなるとCPUユニット値のバランスが大事になってきそうです。では、コンテナ数を5個に固定して、4つのパターンで sysbenchをそれぞれ 1000回実行しました。
パターン | 個々のCPUユニット値 | 総CPUユニット値 | 処理時間平均 | 中央値 | 最大値 | 最小値 |
---|---|---|---|---|---|---|
1 | 8,16,32,64,128 | 248 | 10.126175 | 10.081437 | 10.221603 | 10.017635 |
2 | 16,32,64,128,256 | 496 | 10.109149 | 10.071799 | 10.191968 | 10.018893 |
3 | 32,64,128,256,512 | 992 | 10.112341 | 10.072511 | 10.182053 | 10.028173 |
4 | 64,128,256,512,1024 | 1984 | 10.124959 | 10.074736 | 10.162925 | 10.027164 |
結果からだけを見ると、パターン2が最も良い性能になりました。しかし、どのパターンも処理時間にかなりのバラツキが見られます。グラフを見ると、CPUユニット値が小さいほど処理時間がかかっています。また、CPUユニットの差が大きいほど、グラフで言うとパターンの番号が大きくなる程、処理時間にバラツキが見られます。
こうして比較してみると、CPUユニット値が異なる複数のコンテナを動かす場合は、下記の事が言えるかと思います。
- CPUユニット値の最大値と最小値の差は小さい方が待ち時間の差が出ないため処理時間のバランスがよくなる。
- CPUユニット値の合計は小さな値でまとめた方がよい。
ここは、時間があったらもう少し深堀りしたいと思います。
他IOxプラットフォームとの比較
同じCPUユニットを使えば、IOxプラットフォームを変えても「同様のパフォーマンス」が得られるということなので、全く同じプロファイルで、Cisco IR809と比較してみました。
略称 | HW | CPU | IOx用メモリ | OS |
---|---|---|---|---|
IR1101 | Catalyst IR1101 Rugged Series Router | ARMv8 4-Core 600MHz | 862MB | IOS-XE 17.3.4 |
IR809 | Cisco 809 Industrial Integrated Services Router | Intel Atom C2308 2-Core 1.2GHz | 767MB | IOS 15.9.3M4 |
IR809の仮想化環境はハイパーバイザ型です。2コアですが1コアをIOSが専有しており、もう1つのコアでハードウエア管理ホストとIOxが動いています。IOSのコンフィグで、IOxに割り当てるリソースを指定できます。最大の90%を指定しました。
どちらもDocker型IOxアプリを使い、ベンチマークは同じくsysbenchを使いました。
CPUユニット、メモリ、ディスクサイズは、それぞれ 512, 64, 2 と設定しました。
HW | 表示CPUユニット | EPS | 処理時間 |
---|---|---|---|
IR809 | 732 | 228.40 | 200.378586 |
IR1101 | 1255 | 1158.54 | 200.259878 |
HW | TH | EPS |
---|---|---|
IR809 | 1 | 228.80 |
IR809 | 1 | 228.40 |
IR1101 | 2 | 1158.54 |
IR1101 | 2 | 2027.65 |
「リソースに空きがあれば割り当てられる」ので、CPUユニットは512を指定したものの最大まで割り当てられると考えられます。
Platform Support Matrixの値が IOxアプリの性能比を示しているとすれば、IR1101と IR809の CPUユニット値を当てはめると 1255 : 732
なので、IR809のベンチマークの結果は約750 (= 732*1158.54 / 1255 * 10/9) になると予想できます が、実際は3分の1以下でした。
リソースプロファイルの説明では、CPUユニットは基準となるCPUの性能に対する比になっているとあります。IR1101と IR809のそれぞれのベンチマークの結果がCPUユニット値の比になっていないのは、「標準的なベンチマークツール」の実行環境の違いではないかと予想できます。これは第一にIOxアプリのタイプ、つまり仮想環境の違いが挙げられると思います。
したがって、CPUユニットが同じでも、異なるIOxプラットフォームで必ずしも同じ性能がでるとは限らないと言えそうです。
まとめ
今回は、Cisco Catalyst IR1101 IOxの CPUユニットについて深堀りしてみました。
様々な測定結果から下記の事が言えると思います。
- コンテナが1つであれば、CPUユニットの値に関係なく全てのリソースが割り当てられる。
- 複数のコンテナを動かす時に、
- 同じCPUユニット値であれば、平等に待ち時間が割り当てられる。
- 異なるCPUユニット値であれば、大きい方が待ち時間が短くなる。
- CPUユニット値の最大値と最小値に開きがある場合は、小さい方の待ち時間が長くなる。
- CPUユニットが同じでも、異なるIOxプラットフォームで必ずしも同じ性能がでるとは限らない。
- Platform Support MatrixのCPUユニットはIOxアプリの性能比になっているわけではない。
なお、結果はgithubに置いてありますので、興味のある方は解析してみて下さい。解析に使ったツールも githubの iox-benchmarkに置いてあります。
sysbenchは連続でCPUをぶん回しますが、普通のアプリの作りをすればこの様な動き方はしませんので、今回の結果は最悪ケースだと考えて下さい。
IOxはプラットフォームによって構造が少しずつ異なるため、今回の予想が全てのプラットフォームに当てはまるとは言えませんが、参考にはなるかと思います。いつか機会があれば、他のIOxプラットフォームでも測定してみたいと思います。
また、色々なパターンで数百回5も IOxアプリを起動して削除してを繰り返しました。この作業はスクリプトを使って自動化しています。機会があれば、この自動化についても書いてみたいと思います。
師走も半ばを迎えました。2022年🐯まで後少しです。何かと忙しい💦時期になりますが、くれぐれもお体にお気をつけください。
ここまで読んで頂きまして、ありがとうございました。
免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、私の所属する組織の意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、私の所属する組織や他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任から私の所属する組織を免責することに同意したものとします。