すみません、ISUCONのアレに火がついてしまったので..。 Advent Calendarとはとくに関係がありません。
こちらの記事をみて、気になってしまったので interpolateParams
の追加とMySQLチューニングをしてベンチマークを回してみました。
ベンチマークの環境が公開されているのは素晴らしいですね。
8vCPU/16GB Memのc5a.2xlargeなEC2のインスタンスを起動して、以下の手順にしたがってdockerとdocker-composeをインストールしました。OSはUbuntu 20.04を使いました。
上記のbenchmarkのrepositoryをgit cloneし、compose build && compose upします。
$ git clone https://github.com/okdyy75/bench-docker.git $ sudo docker-compose build $ sudo docker-compose up -d
まず何も変更しない状態でのスコア結果は、
$ sudo docker-compose run --rm python sh -c 'cd python; pip install -r ./requirements.txt && time python bench.py' 平均秒数:9.670429 real 1m 36.73s user 0m 6.25s sys 0m 2.79s
Go言語
$ sudo docker-compose run --rm golang sh -c 'cd go; go build . && time ./go' 平均秒数:11.70815524 (0x0,0x0) real 1m 57.08s user 0m 3.84s sys 0m 10.83s
たしかに、Go言語の結果の方が少し悪くなっています。
ここで元記事にてmethaneさんから指摘のあった interpolateParams
の設定をいれます。
diff --git a/www/go/bench.go b/www/go/bench.go index 5c56714..a4b86d0 100644 --- a/www/go/bench.go +++ b/www/go/bench.go @@ -37,7 +37,7 @@ func getDB() *sql.DB { } dsn := fmt.Sprintf( - "%s%s@tcp(%s:%s)/%s?charset=utf8&parseTime=true", + "%s%s@tcp(%s:%s)/%s?charset=utf8&parseTime=true&interpolateParams=true", user, password, host, port, name) db, err := sql.Open("mysql", dsn)
そうすると、結果は
平均秒数:10.540287 real 1m 45.40s user 0m 2.99s sys 0m 6.26s
となり、pythonに追いつかないまでも、改善はしています。
ところで、ベンチマークを何回か動かしながら気になったのは、スコアが振れが大きく、iowaitがそれなりでているとところです。(Maki-Daisukeさんはioの影響を抑えるためNVMe SSDのついたインスタンスを使われておりました)
$ vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 1 0 11964048 140004 3405756 0 0 0 7872 8115 13468 1 2 95 2 0 0 0 0 11964048 140004 3405932 0 0 0 7656 6939 11857 1 2 93 4 0 0 1 0 11956236 140004 3414672 0 0 0 16284 7068 12074 1 1 94 4 0 0 1 0 11956236 140004 3414672 0 0 0 7768 8375 14349 1 2 94 3 0 1 0 0 11956236 140004 3414672 0 0 0 7464 7463 12275 2 1 96 2 0 0 1 0 11955480 140004 3415720 0 0 0 8780 7971 12701 2 1 97 0 0 0 1 0 11955480 140004 3415720 0 0 0 7712 8561 13845 1 2 97 0 0 0 1 0 11955480 140004 3415720 0 0 0 7780 7966 13032 1 1 96 1 0 0 1 0 11954472 140004 3416496 0 0 0 8788 7051 12944 2 1 90 7 0 0 1 0 11964536 140004 3405576 0 0 0 9592 9176 16006 2 1 92 4 0 2 0 0 11964284 140004 3405832 0 0 0 8220 7737 13731 1 1 92 5 0 1 0 0 11964252 140004 3405928 0 0 0 8056 8078 12893 1 1 97 0 0 0 1 0 11955416 140004 3414756 0 0 0 16132 6565 11829 1 1 91 7 0 2 0 0 11955416 140004 3414756 0 0 0 7056 7333 12482 1 1 94 3 0
また、CPUも全然使えてません。
これはMySQL側がボトルネックになっている可能性が高いとみて、対ISUCON用秘伝のタレを投入して、再度実行してみました。
my.cnf を作成。4つのパラメータを追加
$ cat docker/mysql/my.cnf [mysqld] innodb_doublewrite = 0 innodb_flush_log_at_trx_commit = 2 innodb_flush_method = O_DIRECT_NO_FSYNC innodb_adaptive_hash_index = 0
compose.ymlに追記して、mysqlを再起動
$ git diff diff --git a/docker-compose.yml b/docker-compose.yml index 94b3dc7..e39de9b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,7 @@ services: volumes: - "./.data/mysql:/var/lib/mysql" - "./log/mysql:/var/log/mysql" + - "./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf" ports: - "3306:3306" # php-fpm ################################################ $ sudo docker-compose restart mysql Restarting bench-docker_mysql_1 ... done
結果は
平均秒数:1.518821 real 0m 15.21s user 0m 6.12s sys 0m 1.69s
Go言語(interpolateParams=false)
平均秒数:1.770360 real 0m 17.70s user 0m 3.04s sys 0m 7.85s
Go言語(interpolateParams=true)
平均秒数:1.196632 real 0m 11.96s user 0m 2.26s sys 0m 4.95s
interpolateParamsが有効のGo言語が最速になりました。最初の10倍近い高速化ですね。
MySQLが高速化したことで順位が入れ替わるところはもう少し深堀してもいいかと思いますが、Pythonにしたってかなり速くなってますので、これくらいなら正直どの言語でやってもいいのではないかと思います。仲良くしましょう
Go言語を実行中のvmstatは以下のようになりました。
vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 12075152 140028 3363636 0 0 10 453 441 22 1 1 98 1 0 0 0 0 12075152 140028 3363636 0 0 0 0 139 257 0 0 100 0 0 0 1 0 12015176 140028 3387952 0 0 0 25772 1950 2773 5 1 93 1 0 1 0 0 11968016 140028 3391408 0 0 0 12732 31447 60372 9 7 84 1 0 1 0 0 11967732 140028 3391376 0 0 0 4660 42484 86361 7 8 85 0 0 1 0 0 11967748 140028 3391360 0 0 0 14592 35933 73675 6 6 87 1 0 1 0 0 11967256 140028 3391228 0 0 0 6964 38245 77879 7 7 86 0 0 2 0 0 11966928 140028 3391416 0 0 0 13028 36928 75262 6 7 87 0 0 2 0 0 11966816 140028 3391440 0 0 0 7352 37506 76638 7 7 86 0 0 1 0 0 11968984 140028 3391440 0 0 0 14120 32657 71858 8 7 85 0 0 1 0 0 11969976 140028 3391468 0 0 0 15564 33490 69433 7 7 86 1 0 2 0 0 11969976 140028 3391468 0 0 0 3392 40593 82689 7 8 85 0 0 1 1 0 11971740 140028 3391440 0 0 0 15568 35473 72960 6 7 86 1 0 2 0 0 11973520 140028 3391476 0 0 0 5420 36698 76628 8 7 85 0 0 1 0 0 11973344 140028 3391476 0 0 0 13000 37315 77527 6 7 87 0 0 1 0 0 11973392 140028 3391536 0 0 0 8284 34950 71476 6 8 86 0 0 2 0 0 11973408 140028 3391536 0 0 0 13840 38778 79834 6 7 86 1 0 1 0 0 11974132 140028 3391544 0 0 0 8692 37283 74883 7 7 86 0 0 3 0 0 11974132 140028 3391544 0 0 0 10444 37224 77928 6 8 86 0 0 2 0 0 11973108 140028 3391608 0 0 0 15688 34599 71052 6 7 86 1 0 0 0 0 11980788 140028 3391728 0 0 0 6868 33311 72294 7 8 84 0 0 0 0 0 12069692 140028 3363668 0 0 0 2588 2979 4393 1 1 98 0 0
iowaitが小さくなり、user, systemが以前より高くあがるようになりました。
topだと
top - 07:43:15 up 2:16, 2 users, load average: 0.43, 0.11, 0.05 Tasks: 169 total, 1 running, 168 sleeping, 0 stopped, 0 zombie %Cpu(s): 6.2 us, 3.9 sy, 0.0 ni, 85.9 id, 0.4 wa, 0.0 hi, 3.6 si, 0.0 st MiB Mem : 15827.2 total, 11689.1 free, 689.4 used, 3448.7 buff/cache MiB Swap: 0.0 total, 0.0 free, 0.0 used. 14833.8 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 44962 systemd+ 20 0 1377796 216128 20612 S 77.4 1.3 1:29.73 mysqld 47046 root 20 0 710064 10828 3836 S 60.5 0.1 0:06.25 go
ようになり、1vCPU 使い切りそうなぐらいまできてました。
ちなみに、MySQLのデータディレクトリをみんな大好きtmpfsにおくと、
Go言語(interpolateParams=true)
平均秒数:1.106469 real 0m 11.06s user 0m 2.45s sys 0m 5.07s
平均秒数:1.394543 real 0m 13.97s user 0m 6.15s sys 0m 1.70s
もう少しだけ速くなります。
まとめ
ミドルウェア含めたベンチマークを行う時は、ミドルウェアやOSの設定なども気を配るのがいいですね。広い視点を保つためもにもISUCONは役に立つ。