これは何?
性能周りの知見向上のため、ISUCON過去問を触ってみたい!と思い至りました。 本記事はそのための第一段階としてLocalで環境構築してみた時の備忘録です!
Localでアプリ立ち上げ + ベンチマークを回す、ことをゴールとしています。 「推測するな計測せよ」の第一歩ですね。
公式 github.com
【前提】自分の要望
- ISUCON慣れするまでAWS環境とか使わず、金はかけたくない
- MySQLが必要だが、LocalPCに直接インストールするのは嫌だ
上記二点から、Local環境でDB部分だけDocker-Composeで構築してみます。
成果物
- 公式をForkしてちょっといじったもの
- 上記の差分
実行環境
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
初期データ生成
※公式と同じ手順
ルートディレクトリから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句直後に以下追加(文字化け防止)
SET CHARACTER_SET_CLIENT = utf8; SET 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")
公式にも書いてありました。
各ステップで失敗が見付かった場合にはその時点で停止します。 ただし、負荷走行中のエラーについては、タイムアウトや500エラーを含む幾つかのエラーについては無視され、ベンチマーク走行が継続します。
参考文献
公式サイト
有志ブログ(Dockerは使ってるけどdocker-composeじゃない)