ISUCON12 予選突破

チーム「と」最終31962点で11位。

github.com

方針

「まずは SQLite のまま進める。テーブル単位で徐々に MySQL に載せ替えつつも、ボトルネック解消に専念し1台でこれ以上大きく伸びなそう。と思うタイミングで複数台使う。大体16時ごろを目処」と思っていたが、結局上手くいかず何も MySQL に載せることはなく最後まで1台のまま進めることにした。また、最後の1時間で MySQL だけでも分けようとも思ったが、ログ出力を消したことで FAIL するようになったことの対応に追われて叶わず。

スコアを伸ばせたのは

  • MySQL ネックの解消
    • visit_history への index 追加と dispenseID の xid 化
  • SQLite に対する非効率なクエリの解消
    • visitor/player count と rank を都度計算せずに保存する
    • score の bulk insert

ぐらいだったと思う。

使ったツール

  • alp
  • pt-query-digest
  • pprof
  • top

やったこと

錯乱しながら作業していたのであまり正確ではない。

  • 10:00 - 13:00
    • 配信を見るのを忘れていて慌てて見る
    • コードを一通り読む
    • Docker 剥がし
    • デプロイスクリプトを用意する
    • visit_history に index を貼る
    • dispenseID で xid を使う
  • 13:00 - 14:45
    • pprof の有効化
      • MySQL ネックではなくなったので、この後 pt-query-digest は使わずに pprof と top だけ見ていた
    • 何も前進せず予選敗退の恐怖に支配され心が折れかける
  • 14:45
    • 妻に「切り替えてやれ」と凄まれ、自然と予選敗退の恐怖は消えさった。妻に感謝
  • 14:45 - 16:00
    • competition テーブルに visitor_count / player_count 追加
      • 大会終了時に計算して UPDATE
  • 16:00 - 17:00
    • ranking (competition_id [pk], ranking [pk], score, player_id [idx1], player_display_name) テーブルを追加して、ページングして取得できるようにする
      • /api/player/player/:player_id でもこのテーブルを使った
    • initialize が timeout するようになったので雑に並列に insert 投げて、sleep 2s している。sync.WaitGroup 使えよという感じがするが、FAIL を繰り返していたのでとにかく通したいという思いが先行した。
    • player_score を bulk insert にする
  • 17:00 - 18:00
    • go-json を使う
    • ログ出力をやめると to many files が出るようになったので LimitNOFILE を設定
    • keepalive や connection pool のサイズを変更したりしたが特段効果なし

改めて振り返ると無駄なことで時間を消費していたことが分かるし、やろうと思ったことは全然出来なかった。ただ、時間内でもっと出来たとは思えず、まあまあうまくいったほうじゃないかなという気がしている。

このままでは本戦を戦えなさそうなので、何度か練習しておこうと思う。