品質 負荷試験

【性能】ISUCON9予選のLocal環境構築(DB部分:Docker-Compose)

2023年1月2日

性能周りの知見向上のため、ISUCON過去問を触ってみたい!と思い至りました。
本記事はそのための第一段階としてLocalで環境構築してみた時の備忘録です!

Localでアプリ立ち上げ + ベンチマークを回す、ことをゴールとしています。
「推測するな計測せよ」の第一歩ですね。

公式
github.com

【前提】自分の要望

  • ISUCON慣れするまでAWS環境とか使わず、金はかけたくない
  • MySQLが必要だが、LocalPCに直接インストールするのは嫌だ

上記二点から、Local環境でDB部分だけDocker-Composeで構築してみます。

成果物

  • 公式をForkしてちょっといじったもの

github.com

  • 上記の差分

github.com

実行環境

MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)

プロセッサ 2.3GHz デュアルコア Intel Core i5

メモリ 8GB

TODO

Git Clone

※公式と同じ手順

git clone git@github.com:isucon/isucon9-qualify.git

github.com

初期データ生成

※公式と同じ手順

ルートディレクトリからinitial-data直下に移動し、makeコマンドを叩く。

cd initial-data
make

具体的には...

  • Makefileを元に、中でPerlが動くコンテナができる
  • tsvファイルを元に、初期構築時に使うSQLを生成してくれていたりする
    • 大容量(125MB)のものがあるのでGit管理せずLocalで作らせてるんだと思う

実行するとこんな感じになります。

画像データ準備

以下コマンドを叩く。
※公式と同じ手順

$ cd webapp/public
(GitHub releases から initial.zip をダウンロード)
$ unzip initial.zip
$ rm -rf upload
$ mv v3_initial_data upload
$ cd initial-data
GitHub releases から bench1.zip をダウンロード
$ unzip bench1.zip
$ rm -rf images
$ mv v3_bench1 images

以下補足。

  • 1.5GBのzipを落とすので、ネットワーク良いところでやろうね
  • 最終的には以下になればOK
    • webapp/public/upload直下にinitial.zip解凍後の画像ファイルがたくさんある
    • initial-data/images直下にbench1.zip解凍後の画像ファイルがたくさんある

MySQL環境生成(Docker利用)

ここから公式と異なる手順になります。
DB部分をDocker-Composeで作っていきます。

docker-compose.yml作る

ルートディレクトリ/webapp/sqlに以下ファイルを生成

version: '3'
services:
db:
image: mysql:8.0
container_name: isudb
environment:
MYSQL_ROOT_PASSWORD: secret
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
#- ./datadir:/var/lib/mysql #永続化させたい場合はコメントアウト外す
- ./conf/my.cnf:/etc/mysql/conf.d/my.cnf
- ./sqlfiles:/docker-entrypoint-initdb.d
ports:
- 3306:3306

ファイル構成修正

最終的なファイル構成はこちら。

webapp
- sql
- conf
- (空)
- sqlfiles
- 00_create_database.sql
- 01_schema.sql
- 02_categories.sql
- 03_initial.sql
- docker-compose.yml
- .gitignore

TODO

  • webapp/sql直下にsqlfilesディレクトリを作ってその中にsqlを移動
    • 00_create_database.sql
    • 01_schema.sql
    • 02_categories.sql
    • initial.sql
  • 02_categories.sqlとinitial.sqlのuse句直後に以下追加(文字化け防止)
CHARACTER_SET_CLIENT = utf8;
CHARACTER_SET_CONNECTION = utf8;
  • initial.sqlを03_initial.sqlに改名
    • docker内で流れるsqlがアルファベット順になる(後述)ため、INSERT文を最後に

コンテナ起動

webapp/sql直下でdocker-compose up -d以下を実行。起動すると以下(Docker for Desktop)のようにコンテナが生成されます。

Goでアプリケーション起動

webapp/go直下でGO111MODULE=on go run api.go main.go実行
※公式と同じ手順

ベンチマーク実行ファイル生成

ルートディレクトリでmake実行
※公式と同じ手順

binディレクトリ配下にベンチマーク起動ファイルが生成されます。
同時にshipment,payment起動ファイルも生成されます。

ベンチマーク起動

ルートディレクトリで./bin/benchmarker実行
※公式と同じ手順

結果

スコアは910でした。ネットに転がってるやつより結構低いですが、これがなんでなのかは不明。。
ゴールである「ベンチマークを回す」は成功したので、ここで終了!

補足

文字コードの話

  • initial.sqlに文字コード指定をつけない場合、以下の「データが長すぎる」エラーでMySQLコンテナがうまく立ち上がらないことがあった。

ERROR 1406 (22001) at line 3: Data too long for column 'name' at row 78

以下でも同じことが起きてそう。

ちゃんと文字コードはあわせましょうbyRails+MySQL - これでも…

タイムアウトエラー

ベンチマーク走行の最後に以下のようなタイムアウトエラーが出るが、ベンチマークの成功失敗には直接影響しない
逆に機能レベルでエラーがあるとスコアが出ると止まる模様。

2023/01/02 20:28:39 fails.go:72: [session.(*Session).Login] /Users/masahiro.yamane/Documents/workspace/isucon/isucon9-qualify/bench/session/webapp.go:249
message("POST /login: リクエストに失敗しました")
[session.(*Session).Do] /Users/masahiro.yamane/Documents/workspace/isucon/isucon9-qualify/bench/session/session.go:186
code(error timeout)
*url.Error("Post \"http://127.0.0.1:8000/login\": context deadline exceeded")

公式にも書いてありました。

github.com

各ステップで失敗が見付かった場合にはその時点で停止します。 ただし、負荷走行中のエラーについては、タイムアウトや500エラーを含む幾つかのエラーについては無視され、ベンチマーク走行が継続します。

参考文献

公式サイト

isucon.net

有志ブログ(Dockerは使ってるけどdocker-composeじゃない)

cha-shu00.hatenablog.com

追記: Localで環境構築するの撤退しました

hiro-tracks.net

-品質, 負荷試験