性能周りの知見向上のため、ISUCON過去問を触ってみたい!と思い至りました。
本記事はそのための第一段階としてLocalで環境構築してみた時の備忘録です!
Localでアプリ立ち上げ + ベンチマークを回す、ことをゴールとしています。
「推測するな計測せよ」の第一歩ですね。
【前提】自分の要望
- 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句直後に以下追加(文字化け防止)
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")
公式にも書いてありました。
各ステップで失敗が見付かった場合にはその時点で停止します。 ただし、負荷走行中のエラーについては、タイムアウトや500エラーを含む幾つかのエラーについては無視され、ベンチマーク走行が継続します。
参考文献
公式サイト
有志ブログ(Dockerは使ってるけどdocker-composeじゃない)
追記: Localで環境構築するの撤退しました