Dockerに割り当てるリソースを制限して、よりリアルにローカルでISUCON10の予選問題を実行する
2020年9月12日に開催されたISUCON10の予選の問題が公開されました。予選のときとは異なり、公開版は全ての要素(チューニング対象のAPIサーバ、MySQL、ベンチマーカー)がDockerコンテナ化されているので、READMEに書いてある順序でmakeを実行すればベンチマークを実行して点数を出すことができます。
実行するのに必要なツール類は下記です。
- Docker (Compose含む)
- pip3
- go
- make
実行してみる
手元の環境では偶然TCP1323が使われていてAPIサーバにつながらない事象がありましたが、それ以外はすんなりと点数を出すところまでいきました。
ベンチマーカーの結果を見ると1500点前後が出ています。これは上位20%のスコアで、実際の予選環境での初期スコアが400前後だったことを考えると、かなり高くなってしまうことがわかります。 最近のISUCONのベンチマーカーは負荷を適応的に上げていく機構が盛り込まれていることがよくありますが、負荷レベルが9まで上がっていることも確認できます。
2020/09/19 02:23:50 bench.go:110: 最終的な負荷レベル: 9 {"pass":true,"score":1560,"messages":[{"text":"POST /api/estate/nazotte: リクエストに失敗しました (タイムアウトしました)","count":55}],"reason":"OK","language":"go"}
公式の講評にもこのように書かれているとおり、本来はDBがネックになる問題なのですが、DBが複数のコアを使っているので性能が上がってしまっていることがわかります。
DB の CPU が100%に張り付くケースが多いです。しかも1台分のスペックはそこまで強くありません ISUCON10 予選問題の解説と講評 : ISUCON公式Blog
$ docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 419297d07565 docker-compose_api-server_1 46.38% 36.68MiB / 25GiB 0.14% 209MB / 202MB 0B / 0B 23 5cf91f529276 docker-compose_mysql_1 343.88% 256.6MiB / 25GiB 1.00% 58.4MB / 196MB 0B / 0B 38
Docker Composeにリソース制限の設定を追加する
Dockerコンテナに割り当てるリソースを少なくしてリアリティのあるスコアを目指します。
配布されているDocker ComposeのYAMLはv3形式なので、 resources
によるリソースの制限はSwarmモード専用なのかと思いつつ調べていたら、 --compatibility
フラグを付けることでv2の動作を再現できることが分かりました。
webapp/docker-compose/go.yaml
の mysql
と api-server
にそれぞれ下記を追記します。
deploy: resources: limits: cpus: 1 memory: 2048M reservations: cpus: 1 memory: 128M
webapp/Makefile
に測定対象のコンテナを起動するためのコマンドが記載されているので、 --compatibility
フラグを追記して make isuumo/go
を実行します。
ストレージのIOPS性能は高いままになってしまいますが、今回はIOがネックになっているようには感じられなかったのでそのままにします。
リソース制限後のベンチ実行、結果
リソースの制限が効いた状態で再度ベンチマーカーを走らせると、DBが1コアを使い切るという実際の状況を再現できました。 またスコアも実際の初期スコアに近い391、負荷レベルも1のままになりました。
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 31b849a0bd49 docker-compose_api-server_1 27.50% 17.33MiB / 2GiB 0.85% 41.4MB / 70MB 0B / 0B 21 4e5ec3c8d814 docker-compose_mysql_1 101.30% 255.7MiB / 2GiB 12.49% 32.5MB / 39.7MB 0B / 0B 39 2020/09/19 02:19:59 bench.go:110: 最終的な負荷レベル: 1 {"pass":true,"score":391,"messages":[{"text":"POST /api/estate/nazotte: リクエストに失敗しました (タイムアウトしました)","count":5}],"reason":"OK","language":"go"}
予選当日は下記のようにテーブル追加作戦が失敗してしまったので、どこでベンチマーカーが通らなくなってしまったのか検証してみたいと思います。
featureのTABLE追加はレスポンス不正の不具合が取れず断念 ISUCON10に参加した #isucon - つばくろぐ @takamii228
2020年9月22日追記 上記の不具合は追加テーブル用のデータを作成するときに、初期データではなくベンチマーク実行後のデータから加工したので、ベンチマーカーを再実行すると一意制約に違反してデータが追加できなくなっていたのが原因でした(´・ω・`)