Yahoo Cloud Serving Benchmark(YCSB)でGemFireの性能測定を実施する

[Yahoo Cloud Serving Benchmark(YSCB)](https://github.com/brianfrankcooper/YCSB)([公式wiki](https://github.com/brianfrankcooper/YCSB/wiki))は様々なデータストアのパフォーマンスを評価するためのツールである。
GitHub上では個人のプロジェクトになっているが、一応ちゃんと[Yahooからリリースされた](https://research.yahoo.com/news/yahoo-cloud-serving-benchmark/)ものの模様。
今回はこれを使ってGemFireの性能測定を実施する。

## 事前準備
YCSBの最新版は2019年にリリースされた0.17.0のようなので、こちらを使って実行する。
最初にダウンロードして解凍する。
```
curl -O --location https://github.com/brianfrankcooper/YCSB/releases/download/0.17.0/ycsb-0.17.0.tar.gz
tar xfvz ycsb-0.17.0.tar.gz
cd ycsb-0.17.0
```
また実行にはpython2が必要なのでインストールする。
```
sudo yum install python2
sudo ln -s /usr/bin/python2 /usr/bin/python
```


GemFireのOSS版である[Geode](https://geode.apache.org/)のやり方が[ここ](https://github.com/brianfrankcooper/YCSB/tree/master/geode)にあるので、こちらの手順に従って実施する。
gfshを起動する。
```
gfsh
```
Locator、Serverを作成する。なお、シリアライズも必要な模様。
```
gfsh> start locator --name=locator1
gfsh> configure pdx --read-serialized=true
gfsh> start server --name=server1 --server-port=40404
gfsh> start server --name=server2 --server-port=40405
```
最後にRegionも作成する。Region名は固定になっており、`usertable`から変更することは出来ないっぽい。
```
gfsh>create region --name=usertable --type=PARTITION
```
以上で準備は終了となる。

## 性能測定

YCSBでデータを流して性能測定を行っていく。
コマンドはデータを乗せる`load`と負荷を掛ける`run`の2回に分けて実行する。
```
./bin/ycsb load geode -P workloads/workloada -p geode.locator=10.215.76.208[10334]215.76.208[10334]
./bin/ycsb run geode -P workloads/workloada -p geode.locator=10.215.76.208[10334]215.76.208[10334]
```
オプションはそれぞれ以下の意味となる。
- `load`,`run`：YCSBの実行モードを指定する。データをloadするオプションである`load`モードと、トランザクションを実行する`run`モード、対話型で処理を行う`shell`モードがある
- `geode`：対象DB種別を選択。今回はGemFireと互換性のある`Geode`を選択
- `-P workloads/workloada`：ワークロードを定義したファイルを選択（後述）
- `-p geode.locator=10.215.76.208[10334]`：パラメータを上書きする。ここではLocatorを指定。

ワークロードについてはデフォルトで5つの定義したファイルが存在する。
公式wikiの[Core Workloads](https://github.com/brianfrankcooper/YCSB/wiki/Core-Workloads)に説明があるが、ざっくり以下のような意味になる。
- WorkLoad A：Read50％、Write50%
- WorkLoad B：Read95％、Write5%
- WorkLoad C：Read100％、Write0%
- WorkLoad D：新規データへのアクセスが人気となるような負荷
- WorkLoad E：個のデータではなく、ある程度の範囲に対するアクセス
- WorkLoad F：Read、更新、Writeを実施

WorkLoadに関しては[自作することも可能](https://github.com/brianfrankcooper/YCSB/wiki/Implementing-New-Workloads)なので、元々用意されているワークロードが不十分な場合は自作すると良さそう。

なお、今回利用したワークロードの`workloada`が具体的に何をやっているか、もう少し具体的に見てみる。
```sh
# Yahoo! Cloud System Benchmark
# Workload A: Update heavy workload
#   Application example: Session store recording recent actions
#
#   Read/update ratio: 50/50
#   Default data size: 1 KB records (10 fields, 100 bytes each, plus key)
#   Request distribution: zipfian

recordcount=1000
operationcount=1000
workload=site.ycsb.workloads.CoreWorkload

readallfields=true

readproportion=0.5
updateproportion=0.5
scanproportion=0
insertproportion=0

requestdistribution=zipfian
```
ここでのパラメータは以下の意味となる（参考：[Core Properties](https://github.com/brianfrankcooper/YCSB/wiki/Core-Properties)）。
- `recordcount`：負荷開始時のレコード数
- `operationcount`：ワークロードで実行する操作の数
- `workload`：ワークロードを掛ける本体
- `readallfields`：全てのフィールドを読む場合は`true`、1つのフィールドを読む場合は`false`を指定
- `readproportion`：Readの操作の割合
- `updateproportion`：更新の操作の割合
- `scanproportion`：スキャンの操作の割合
- `insertproportion`：挿入の操作の割合
- `requestdistribution`：データのばらつきを指定（`uniform`, `zipfian`, `hotspot`, `sequential`, `exponential`、`latest`が選択可能）

workloadaの場合、1000レコードを読み込み、1000回アクセスし、readとwrite(update)を半々の割合で実行することが分かる。
実際に`workloada`を使って`load`を実行した結果は以下となる。
```sh
$ ./bin/ycsb load geode -P workloads/workloada -p geode.locator=10.215.76.208[10334]215.76.208[10334]
：（省略）
[OVERALL], RunTime(ms), 4655
[OVERALL], Throughput(ops/sec), 214.82277121374867
：（省略）
[INSERT], Operations, 1000
[INSERT], AverageLatency(us), 2626.161
```
上記のように全体のスループットとデータ登録のレイテンシが表示されればOKとなる。
なお、ここでRegionの中身を見ると以下のようなデータが入っている。（以下はGemFire Management Consleを使って確認したもの）
![1701155288954.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/57abe4e8-07f0-fd14-75bf-e0d59cfa202e.png)

`load`実行後、`run`を実行した結果は以下となる。
```sh
$ ./bin/ycsb run geode -P workloads/workloada -p geode.locator=10.215.76.208[10334]215.76.208[10334]
：（省略）
[READ], Operations, 519
[READ], AverageLatency(us), 476.28131021194605
[READ], MinLatency(us), 217
[READ], MaxLatency(us), 16415
[READ], 95thPercentileLatency(us), 800
[READ], 99thPercentileLatency(us), 2531
[READ], Return=OK, 519
：（省略）
[UPDATE], Operations, 481
[UPDATE], AverageLatency(us), 1178.985446985447
[UPDATE], MinLatency(us), 421
[UPDATE], MaxLatency(us), 115199
[UPDATE], 95thPercentileLatency(us), 1499
[UPDATE], 99thPercentileLatency(us), 9767
[UPDATE], Return=OK, 481
```
上記のようにReadとWrite(UPDATE)のレイテンシを取得することが出来た。
最大・最小レイテンシに加えパーセンタイルの値もあるため、ばらつきも測定できる。