クラウドサーバーサービス(IaaS)の性能比較・CPU＆メモリ＆トランザクション編 ～sysbench～

##1. 概要
　AWS,GCP,IDCFクラウドを対象に、sysbench を使ってCPU、メモリ、データベースのトランザクション処理のベンチマークを実行します。IDCFクラウドについては東日本リージョン2のluxと西日本リージョンのmonsteraを計測し、ゾーン間の違いがあるかも計測します。
~~（※ 東日本リージョンでも計測する予定でしたが、sysbenchの実行時にエラーが発生しため測定不能でした。エラーの内容は最後に掲載します。）~~
**※ 2017/06/27 東日本リージョン・henryの結果を追記しました。**

　OLTPテストの実行時には、実環境に近づけるためベンチマークを実行するサーバとデータベースサーバを分けてテストします。AWSとGCPはデータベースサービスを使用します。

| 計測対象                   |sysbenchサーバ|DBサーバ (OLTP用)|
|:---------------------------|-----------:|-----------:|
| Amazon Web Services (AWS)  |        EC2 |        RDS |
| Google Cloud Platform (GCP)|        GCE |  Cloud SQL |
| IDCFクラウド (ゾーン：lux)| 仮想マシン | 仮想マシン  |
| IDCFクラウド (ゾーン：monstera)| 仮想マシン | 仮想マシン  |
| IDCFクラウド (ゾーン：henry)| 仮想マシン | 仮想マシン  |

##2. 条件

###2.1 バージョン

| OS/ミドルウェア   |     バージョン |
|:-----------------|-------------:|
| CentOS           |          7.3 |
| MySQL            |        5.7|
| sysbench         |        1.0.5 |

###2.2 環境

 - **sysbenchサーバ**

| |          ゾーン |                            スペック | ディスクサイズ |
|:------------:|----------------:|------------------------------------:|---------------:|
| **AWS(EC2)** |  ap-northeast-1 |      m4.large <br> (2vCPUメモリ8GB) |            8GB |
| **GCP(GCE)** |asia-northeast1-a|n1-standard-2 <br>(2vCPUメモリ7.5GB) |           10GB |
| **IDCF**     |             lux |    standard.M8 <br>(2vCPUメモリ8GB) |           15GB |
| **IDCF**     |        monstera |    standard.M8 <br>(2vCPUメモリ8GB) |           15GB |
| **IDCF**     |            henry|    standard.M8 <br>(2vCPUメモリ8GB) |           15GB |

 - **DBサーバ（OLTP用）**

|     |          ゾーン |                            スペック | ディスクサイズ |
|:------------:|----------------:|------------------------------------:|---------------:|
| **AWS(RDS)** |  ap-northeast-1 |   db.t2.large <br> (2vCPUメモリ8GB) |          100GB |
| **GCP(Cloud SQL)**|asia-northeast1-a|db-n1-standard-2  <br>(2vCPUメモリ7.5GB) |     100GB |
| **IDCF**     |             lux |    standard.M8 <br>(2vCPUメモリ8GB) |          100GB |
| **IDCF**     |        monstera |    standard.M8 <br>(2vCPUメモリ8GB) |          100GB |
| **IDCF**     |            henry|    standard.M8 <br>(2vCPUメモリ8GB) |          100GB |

##3. sysbenchのインストール
　EPEL レポジトリからsysbenchをインストールします。

```
$ yum install epel-release
$ yum install sysbench
```

##4. cpuテスト

　sysbench のCPUテストでは、指定した最大探索数（デフォルトでは10000）以下の素数を数えるという処理を繰り返し行い、CPUの性能を計測します。

###4.1 テスト内容
　スレッド数を 1 threads, 2 threads, 4 threadsと変更して計測してみます。

実行例）

```
sysbench cpu --threads=1 run > /tmp/sysbench_cpu_1.log
sysbench cpu --threads=2 run > /tmp/sysbench_cpu_2.log
sysbench cpu --threads=4 run > /tmp/sysbench_cpu_4.log
```

>※ sysbench 1.0から構文が変更されています。本稿は1.0の構文で記述しています。

> - sysbench 0.5 :　`$ sysbench --test=<path> [options...] command`
> - sysbench 1.0 :　`$ sysbench [<path>] [options...] [command]`

###4.2 計測結果
>※ sysbench 1.0はデフォルトで合計実行時間が一定となっており、古いバージョンではデフォルトでイベントの合計数が一定となっているため、結果の比較方法が古いバージョンと異なります。

　実行時間はデフォルトで10秒固定となっていました。　以下は制限時間（10秒）内で処理したイベント数の比較です。

| 対象/スレッド数  |        1 |       2 |        4 |
|:----------------:|---------:|--------:|---------:|
| **AWS**          |     8744 |    13927|     14022|
| **GCP**          |     9014 |    15396|     15441|
| **IDCF(lux)**    |     10046|    20075|     18107|
|**IDCF(monstera)**|     10036|    20055|     17962|
| **IDCF(henry)**  |     8317 |    16614|     16647|

<img width="386" alt="cpu3.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/105824/5cc09179-c4b4-9419-b735-a9ab762dbb61.png">

 - スペックが2CPUなので、2スレッドで頭打ちになる結果となっています。
 - AWS < GCP < IDCF の順にCPUの性能がいい事がわかりました。
 - IDCFの東日本リージョン2(lux)、西日本リージョン(monstera)はほぼ同じ、東日本リージョン1(henry)は同じIDCFの中ではやや劣る結果となりました。

##5. memoryテスト
　sysbench のメモリのベンチマークテストでは、メモリに対する連続した書き込みおよび読み出しを行い、`--memory-total-size` で指定されたサイズに達するまで繰り返します。
　オプションやデフォルト値は以下のようになっています。

```
sysbench memory help
sysbench 1.0.5 (using system LuaJIT 2.0.4)

memory options:
  --memory-block-size=SIZE    size of memory block for test [1K]
  --memory-total-size=SIZE    total size of data to transfer [100G]
  --memory-scope=STRING       memory access scope {global,local} [global]
  --memory-hugetlb[=on|off]   allocate memory from HugeTLB pool [off]
  --memory-oper=STRING        type of memory operations {read, write, none} [write]
  --memory-access-mode=STRING memory access mode {seq,rnd} [seq]
```

###5.1 テスト内容
　今回はデフォルト値のまま実行します。

実行例）

```
sysbench memory run > /tmp/sysbench_memory_1_write_seq.log
```

###5.2 計測結果
　1秒あたりのスループットの計測結果を示します。単位はMiB/secです。 

|     AWS |     GCP |IDCF(lux)|IDCF(monstera)|IDCF(henry)|
|--------:|--------:|--------:|-------------:|----------:|
|  1553.80|  2668.44|  4073.40|       4039.96|    4024.16|

<img width="386" alt="memory4.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/105824/48f4322c-d036-ccc9-2d4e-e19d61a52287.png">


 - AWS < GCP < IDCFの順に処理速度が速いことがわかりました。
 - IDCFの東日本リージョン1(henry)、東日本リージョン2(lux)、西日本リージョン(monstera)は、ほぼ同じ結果となりました。

##6. OLTPテスト
　OLTPテストではデータベースへの読み書きを行って性能を測定します。
###6.1データベースの準備
　AWSとGCPは、MySQLを選択してDBインスタンスを作成するだけなので、6.1.2 から実行します。
####6.1.1 MySQLの準備（IDCFのみ）
　IDCFはデータベースサービスが無いので、ディスクの追加・マウント後、下記の手順でMySQLのインストール・起動・設定を行います。

#####6.1.1.1 インストール
　CentOS 7 はデフォルトではmariaDBが導入されるので、MySQL 公式の yum リポジトリを利用してYumリポジトリのインストールをします。

```
$ yum install https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
$ yum install -y mysql-community-server
```

　MySQlのデータディレクトリを追加ディスクに移動します。

```
# mv /var/lib/mysql /data/mysql
# ln -s /data/mysql /var/lib/mysql
```


#####6.1.1.2 起動
　MySQL Server を起動します。

```
$ systemctl start mysqld.service
```

#####6.1.1.3 rootパスワード変更
　MySQL5.7ではroot の初期パスワードがMySQLのログファイルに出力されています。
　ログファイルから初期パスワードを取得します。

```
$ cat /var/log/mysqld.log | grep password | awk '{ print $NF }' | head -n 1
```
　mysql_secure_installationで新しい root パスワードを設定します。

#####6.1.1.4 my.cnf設定
　/etc/my.cnf の以下の値のみ変更しました。各値はRDSに合わせて設定しました。

```
innodb_buffer_pool_size = 6144M
max_connections = 648
```

　MySQLを再起動します。

```
# systemctl restart mysqld.service
```

####6.1.2 測定用データベース作成
　OLTPテストを行うには、あらかじめデータベースにベンチマーク用のユーザーとデータベースを作成しておく必要があります。
デフォルトではデータベース名、ユーザ名ともに「sbtest」になので、以下のように作成しておきます。

```
$ mysql -u root -p
　：
　：
mysql> CREATE DATABASE sbtest;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'sbtest'@'***.***.***.***' IDENTIFIED BY '<パスワード>';
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host from mysql.user;
+-----------+-----------------+
| user      | host            |
+-----------+-----------------+
| sbtest    | ***.***.***.*** |
| mysql.sys | localhost       |
| root      | localhost       |
+-----------+-----------------+

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
```
 - \*\*\*.\*\*\*.\*\*\*.\*\*\* の部分はSysBenchを実行するサーバのIPアドレス又はエンドポイントを指定します。
 - ＜パスワード＞は、データベースのポリシーに合わせて適切な値に変更して実行してください。

###6.2 テスト実行
####6.2.1 測定用テーブルの作成
　テスト用のテーブルを作成し、テストデータを用意します。

```
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--db-driver=mysql \
--oltp-table-size=1000000 \
--mysql-host=<DBサーバのIPアドレス又はエンドポイント名> \
--mysql-password=<パスワード> \
prepare
```

####6.2.2 テスト内容
　スレッド数1, 2, 3, 4, 16, 200, 500 のそれぞれについて、Read OnlyとRead-Writeの2パターンを実行します。

 - Read Onlyの実行例）

```
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--oltp-table-size=1000000 \
--db-driver=mysql \
--mysql-host=<DBサーバのIPアドレス or エンドポイント> \
--mysql-db=sbtest \
--mysql-user=sbtest \
--mysql-password=<パスワード> \
--time=60 \
--events=0 \
--threads=1 \
--oltp_read_only=on run >> /tmp/sysbench_oltp_read_only_1.log
```

 - Read Writeの例

```
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--oltp-table-size=1000000 \
--db-driver=mysql \
--mysql-host=<DBサーバのIPアドレス or エンドポイント> \
--mysql-db=sbtest \
--mysql-user=sbtest \
--mysql-password=<パスワード> \
--time=60 \
--events=0 \
--threads=1 \
--oltp_read_only=off run >> /tmp/sysbench_oltp_read_write_1.log
```
###6.3 計測結果

　計測結果を以下に示します。単位はTransaction per secondです。

- Read Only

| 対象／スレッド数 |         1|         2|         4|        16|       200|       500|
|:----------------:|---------:|---------:|---------:|---------:|---------:|---------:|
| **AWS**          |   228.92 |   405.27 |   615.24 |   804.34 |   791.74 |    721.49|
| **GCP**          |   178.85 |   307.33 |   531.70 |   745.20 |   708.65 |    664.51|
| **IDCF(lux)**    |   314.59 |   493.36 |   700.20 |   973.62 |   927.30 |    882.19|
|**IDCF(monstera)**|   296.45 |   484.28 |   651.48 |   924.41 |   930.86 |    841.27|
|**IDCF(henry)**   |   249.53 |   412.18 |   654.83 |   915.72 |   851.35 |    773.6 |

<img width="386" alt="ReadOnly3.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/105824/05af48c8-6cd5-cafc-13a5-d2e1ba8380ee.png">


- Read Write

| 対象／スレッド数 |         1|         2|         4|        16|       200|       500|
|:----------------:|---------:|---------:|---------:|---------:|---------:|---------:|
| **AWS**          |   100.80 |   188.70 |   320.92 |   538.65 |   598.57 |   553.02 |
| **GCP**          |   103.72 |   197.73 |   318.18 |   543.03 |   534.49 |   515.96 |
| **IDCF(lux)**    |   190.75 |   306.82 |   439.92 |   699.05 |   694.88 |   676.92 |
|**IDCF(monstera)**|   189.57 |   310.65 |   411.68 |   690.48 |   672.42 |   652.98 |
|**IDCF(henry)**   |   119.83 |   207.63 |   341.91 |   542.28 |   592.01 |   556.37 |

<img width="387" alt="ReadWrite3.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/105824/078bdac5-1f91-bc7b-9625-1f300ea4f7ce.png">


 - どのクラウドサーバもスレッド数16以降は性能が横ばいになり、少しずつ低下しています。
 - Read Only では GCP < AWS < IDCF の順にトランザクション性能が高いことがわかりました。
 - Read Wite では AWS と GCP がほぼ同じ結果となり、IDCF はより高い性能を示しました。
 - Read Only では IDCFの東日本リージョン2(lux)、西日本リージョン(monstera)はほぼ同じ、東日本リージョン1(henry)は同じIDCFの中ではやや劣る結果となりました。
 - Read Wite では IDCFの東日本リージョン2(lux)と西日本リージョン(monstera)ほぼ同じ、東日本リージョン1(henry)は大きく劣る結果となりました。
 - IDCFはデータベースサービスが無いのでデータベースの構築とチューニングに手間がかかります。
 
****************************************************************************************
~~##補足：IDCFの東日本リージョンで実施した際のエラー内容~~　
**※ 2017/06/27 再度同じ条件で実行したところ、エラーにならずに実行できたため、以下は削除させていただきます。**

- ~~CPUテスト実行時：~~

```
# sysbench cpu --threads=1 run
sysbench 1.0.5 (using system LuaJIT 2.0.4)

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time


Prime numbers limit: 10000

Initializing worker threads...

Threads started!

Illegal instruction
```

- ~~メモリテスト実行時：~~

```
# sysbench memory run
sysbench 1.0.5 (using system LuaJIT 2.0.4)

Illegal instruction
```

- ~~OLTPテストでprepare実行時：~~


```
# sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--db-driver=mysql \
--oltp-table-size=10000 \
--mysql-host=localhost \
--mysql-db=sbtest \
--mysql-user=sbtest \
--mysql-password=SysbenchPassword1! prepare
sysbench 1.0.5 (using system LuaJIT 2.0.4)

Creating table 'sbtest1'...
Inserting 10000 records into 'sbtest1'
Illegal instruction
```

　~~テストデータをインサートするタイミングで以下のエラーが発生。~~
　~~MySQlにはsbtestテーブルが作成されており、レコードはゼロ件でした。~~
　~~/var/log/mysqld.log には以下のように出力されていました。~~

```
Aborted connection 7 to db: 'sbtest' user: 'sbtest' host: 'localhost' (Got an error reading communication packets)
```

　~~※ henry, jouleの2つのゾーンで同様の現象が発生し、残念ながら今回は測定不能となりました。~~