isucon11予選に参加しました
isucon11 に去年と同じ tockn, 143 と デデデ20 チームを組んで出場してきた 最終スコア 55684 の 65位 (600チーム中) で予選敗退
事前に準備していたこと
バックアップ、デプロイ、計測、ログローテーションあたりを楽にできるMakefileの整備
去年の問題を1回3人で練習した
去年の反省は
計測結果とかログをちゃんと見ずに "なんとなく効きそう" で変更を加えていた
ベンチが失敗しても修正をmasterに入れ続けた
というのがあったので、今回はちゃんと計測した結果から方針を決めること( 推測するな、計測せよ) と、失敗したら即ロールバックして master へのコミットを止めないことを意識した
ブランチ指定してさくっとベンチマーク動かせるようにもしておいた
計測に使ったツール
スコアの推移
https://gyazo.com/dc7088904acda4d85621d133c657cbfb
やったこと
~11:30
レギュレーション、スコア計算方法、失格条件などを3人でしっかり読む
ebiken.icon これ大事
バックアップ
nginx, mysql (今回は MariaDB だった) の設定ファイル (/var/nginx, /var/mysql) DB の dump
リポジトリのgit管理
事前に用意しておいたリポジトリで管理してローカルで開発できるように
最初のベンチマークを動かす。アクセスログとスロークエリを見て方針を決める
スロークエリは long_query_time = 0 にして全部のクエリを見れるようにしていた
~12:30
DBのCPUがボトルネックだったのと isucondition テーブルでスロークエリが出ていたので index を貼ったりクエリを改善
これでスコアが 1,000 -> 18,000 まで上がる
アプリケーションも結構CPU使っていたので、この間に残りの2人は /trend api とかアプリケーションのボトルネック解消を進めてくれてます
~15:30
3:00くらいまであまり効果のある改善をいれられず、スコアが停滞
ebiken.icon ここがもったいなかったので、分担せず1つひとつ着実に入れていけばよかったかも
自分は /trend api の修正を引き継いでやってた
O(n^2) になっていたDBのクエリを、Redisの sorted set を使って修正 最新の timestamp のものだけ入れればよかったので、 score を timestamp に、member を id:condition にしたものをキャラクターごとに作成
キャラクターの数は少なかったので、それぞれ sorted set を作っても問題ないと判断
これで 20,000 くらいまで上がる
ebiken.icon 大きめの実装だがスムーズに入れられて点数が伸びたので盛り上がった
この後 app, mysql のコネクション数を増やしたりいくつかチューニングして 25,000 くらいまで上がる
このあたりで 143 がDBに入っていたicon画像をファイルシステムに書き出す対応を入れてくれていたので、DBの cpu使用率が減ったのにはこれも効いてるかもしれない
~17:00
時間が少なくなってきたので、このあたりでサーバーを3台構成に変更
1: nginx, redis
2: app
3: mariadb
用意していたスクリプトがうまく動かず、ちょっと手間取って30mくらいかかった
ebiken.icon 1が結構余裕あったので、ボトルネックになっている app を 1,2 の2台構成にしたほうが良かった。色々ローカルキャッシュしていてすぐにはできそうじゃなかったので断念してしまった
~17:30
複数台構成に変更したところ、点数が1000点から伸びなくなってしまう
アクセスログを確認したところ POST /isucondition に全くリクエストが来てなかったので、一旦作業止めて3人でマニュアルを確認する
環境変数でisuからのリクエスト先を指定するところを変更し忘れていた
同時並行で tockn が POST /isucondition を非同期でバルクインサートする修正に取り掛かっていて、そちらでも点数が1000点から伸びない現象が起きていて原因究明に時間がかかってしまった
ebiken.icon 結構時間を無駄にしてしまったので、3人で早めに確認しておけば良かった
これでスコアが 25,000 -> 38,000 まで上がる
ただスコア出た後、ベンチマーカーが動かなくなってしまう
~終了
143 がやってくれていた condition level を事前に計算して入れておく修正を入れようとしたが、バグがあり入れられなかった
最後にログやデバッグ設定等をすべて切ってベンチを回す
nginx のアクセスログ止める
mariadb のスロークエリ止める
app のログ止める
これで点数が一気に 38,000 -> 50,000 まで上がる
ebiken.icon 最後どのマシンもリソースが余っていたのでもう少し早めに切った状態で試して、最終的に drop_probability を少し下げてベンチを回したかったが時間切れになってしまった
感想
去年は0点で失格だったので、ちゃんと計測してそんなに悪くない順位までスコアを挙げられたという点では成長を感じたが、まだまだ実力不足だなと実感した
ちゃんと修正してスコアに効いたものが少なかった。分担したのにそれぞれが詰まって時間費やしてしまったので、大きめの修正は着実に優先度高いものを判断して一つ一つ入れるようにしたほうが良かった