ISUCON12 の予選を通過しました!
チーム名は快適PandAです。ISUCON11には快適PandApexという名前で参加していました。
当日何をやったことを記録として残しておきます。
メンバー
- arakistic
- das (https://blog.das82.com/post/isucon12q/)
- tinax
今年はDiscordで通話しながら作業しました。
Discord Nitro に登録すれば高画質の画面共有ができるので便利です 🙂
やったこと
9:40
全員で集合してyoutubeのライブ動画を見ていました。
コードフリーズの時間など、全体のおおまかな計画を立てました。
10:00
AWSインスタンスの起動を待っている間、全員でマニュアルを読みました。
10:20
サーバーにプロファイリングツールなどをインストールしていました。欲しいツールを全部自動でインストールしてくれるシェルスクリプトを用意していたのでそれを使いました。
僕はソースコードをgitで管理する準備をしていました。作業中、大量のsqliteデータベースファイルが見えて、mysqlに移行することになるのかなあと思っていました。
10:30 (2500点)
初回ベンチマークを回しました。
10:37 (3930点)
GoのアプリサーバーとDBサーバーを別マシンに分離しました。
そのほうが、アプリサーバーとDBのどちらに負荷がかかっているか判断しやすいと考えたからです。
分離作業は練習の段階で何度も行っていたので、作業自体は一瞬で終わりました。
10:40 (3904点)
DB側のcpu負荷が異常に大きかったので、arakistic氏にindexを貼ってもらい解決しました。
点数がなぜか下がっていますが、たぶん slowlog や pprof などのプロファイラを有効にしたからだと思います(あまり覚えてないです)。
その間das氏はソースコード上のN+1クエリを見つけてTODOコメントを書く作業をしていました。
11:46 (3969点)
Docker上に乗っていると再ビルドが遅く、slowlogなどを見るのも面倒だったので、Dockerを剥がしました。
また、sqlite側のN+1クエリをarakistic氏に修正してもらいました。
これからsqlite側の改善が主になると思ったので、私はsqliteのクエリログから重いクエリを順番にソートして表示する、sqlite版slowlogのようなツールを開発していました。
12:01 (4392点)
arakistic 氏にさらにN+1クエリを改善してもらい、点数が上がりました。
12:20 (6898点)
sqlite版slowlogツールが完成し、解析してみたところ INSERT が遅いことがわかったので、competitionScoreHandler
のfor文の中のINSERTを BULK INSERT に変えたところ、点数が上がりました。
12:32 (7411点)
BULK INSERT が使える場所がもう一箇所あったのでそちらもBULK INSERTに変更しました。また、playersAddHandler
の中で retrievePlayer
というSQLクエリを発行する関数を呼び出していましたが、必要ないことに気づいたので関数呼び出しを排除しました。
12:39 (4727点)
retrievePlayer
という関数が様々な関数から頻繁に呼び出されており、この関数は呼び出しのたびに sqlite にクエリを発行するようになっていたため、das氏が結果をRedisにキャッシュするようにしました。
しかし、点数が下がってしまいました。
理由ははっきりとわかりませんでしたが、pprof で見たところ、redisライブラリの内部関数にかなりの時間が食われていたため、Redisとの通信や構造体のシリアライゼーションのオーバーヘッドが大きすぎたことが原因ではないかと思っています。
そのため、Redis ではなく Go 内の配列にキャッシュデータを保存する計画が立ち上がりました。
~14:55
- tinax: sqlite->mysql にデータ移行
- das氏: Go内に
retrievePlayer
のキャッシュを配置 - arakistic氏:
competitionScoreHandler
のキャッシュ
をやっていました。
sqlite->mysqlのデータ移行は、1.db
というsqliteファイルだけ異常にサイズが大きく、データ移行が終わらず困っていました。
最初から用意されてスクリプトではない、自作のスクリプトを作って挑戦したり、DBのパラメータをチューニングしたりしましたが、結局移行しきれませんでした。
1.db
だけ sqlite のまま使って他は mysql に移行するという、いかにもまずそうな方法も思いつきましたが、面倒だったので結局実行していません。
ほかのチームメンバーはキャッシュを進めていましたが、ベンチがなかなか通らず、この時間はスコアの向上はありませんでした。
去年もこの時間帯は沼っていた気がします。
14:55 (9277点)
arakistic氏が、終了した大会に関してはcompetitionScoreHandler
の結果が変化しないことを利用してキャッシュを行い、スコアが大幅に上がりました。
この改善のおかげでチームメンバーの士気もかなり高まった気がします。
sqlite->mysql の移行はこのあたりで諦めて、sqliteのまま改善を続けていく方向に切り替えました。
TODO 続きを書く
コメントを残す