ISUCON9本選にチーム「いんふらえんじにあー as Code」で参加して11位でした #isucon

ISUCON9にチーム「いんふらえんじにあー as Code」で参加して本選11位でした。 反省点たっぷりで悔しいけど、とても楽しめました。 運営のみなさま、ありがとうございました。

メンバーはいつもの @matsuu @ishikawa84g @netmarkjp の3人で、 役割分担はこれまたいつも通りこんな感じでした。

  • @matsuu バリバリ実装する前衛
  • @ishikawa84g レギュレーションやコードやログやDiscordを見る情報官
  • @netmarkjp 司令塔

最終スコアは8995。今回はディストリビューション非公開と言われていて、CentOS8やCoreOSか!?と構えていたのですが、結局Ubuntu 18.04でした。なのでSELinuxは使わず、docker-composeのせいかAppArmorのエラーもなかったそうで。

利用言語はGoで、最終構成は a 1台のみの nginx(host) - webapp(host) - MySQL(docker-compose) という若干いびつな構成でした。これが最後に効いてきます。

アプリのデバッグというかレビュー力が足りなかったところが完全に足を引っ張っていたので、 アプリを読む力を鍛えていきます。 来年また開催されることを願っているし、 「優勝したらその次は出題したい」という気持ちは第一回の頃から持っています。

経過

最初ベンチが通らず、作戦をたてるも何もないと判断。 まずはコツコツやろうと kataribe と pt-query-digest の結果を見て、

  • /api/train/search をマシにする
  • train_timetable_master train_master station_master あたりにインデックスを張る

に取り組んだところ、インデックスで大爆死しました。

  1. インデックスを張る
  2. ベンチがfailする
  3. インデックスを消す
  4. ベンチがfailしたまま...

インデックスをPrimary Keyにしたり普通のインデックスにしたりして、 ダメなのでデータを戻そうとマニュアルの手順でデータを初期化しようとしたところメモリ不足でサーバがスローダウンして失敗し、 スローダウンの原因がMySQLが出力するログが原因でdockerが太ったことだったのでログをstdoutではなくファイルに変更し、webappはぱっとうまくファイルにできなかったのでdockerから剥がし、、、とやっているうちに13:00を過ぎてしまいました。

※初期化は結局別サーバの物理バックアップを /var/lib/docker/volumes/webapp_mysql/_data に直接投入して解決

そんなこんなで、出力がデータ投入順に依存している必要があることに気づいて起動修正し、 スコア2000を越えたのが15:45でした。 テーブルには PRIMARY KEY が必要だし、順序を意識するクエリには ORDER BY が必要。 「15時間でわかるMySQL集中講座 」にも書いたのにすぐに気づけなかったのが悔やまれます。

チーム内で振り返りしたのですが、我々はアプリのデバッグやレビューに弱いみたいで、 このへんがが絡むと難航しがち。 普段コードレビューをし慣れているわけではないので、このへんは改善が必要そうです。

15:45にスコア2000越えてからはようやくISUCON始まったぜって感じで、 17:30にスコア8600出すまで順調に改善できました。 /api/train/search/api/train/seats を対象に、 N+1緩和とマスタのオンメモリ化を中心にやってました。

UpdatedAt Total Score
15:00:00 1,189
15:45:04 2,469
15:55:16 3,827
17:05:30 4,695
17:24:25 7,357
17:30:03 8,698

17:30の時点でwebappをdockerから剥がしたがゆえにMySQLが自動起動しないことがわかっていて、 まだいろいろ取り組みたかったところはあるものの、 failは避けようということで自動起動対応に着手。 結局自動起動対応が17:59までかかってギリギリfinishでした。

UpdatedAt Total Score
17:37:45 0
17:40:01 7,029
17:41:42 7,132
17:43:36 7,551
17:45:41 9,107

〜15:45のドハマりを、遅くとも13:00くらいまでに収められるようになりたい。 17:30の時点で↓は認識していたので、このくらいはやりたかったなぁ。

  • cancel APIのバルク化
  • MySQLのdocker-proxy がCPUを食っていたので webapp - MySQLをUnix Doamin Socketに変更

今回は予選も本選も、シナリオ的側面のベンチマーカーの作り込みが凄くて素晴らしかったです。

繁忙期の話だったり、 隣り合い座席のアサインだったり、 区間ごとの空席判断の効率化だったり、 まだかなりスコア伸び代がありそうな感じがしています。

ベンチマーカーは動作も結果も安定してて素晴らしかったです。 (結果のほうはベンチマーカーが不安定になるところまで行けなかっただけかも) 1点単位で計測してるのに、2回連続でやって1の位まで同じとかもうね。。。 エンキューから実行が早すぎて、ベンチが即failしたのがベンチマーカー側で何か問題が出てるんじゃないかと疑っちゃうレベルでした。

余談

TimezoneがCSTなのはいいとして、 tmuxのステータスラインに が出てたのは何なんだろう...

余談2

11位という結果をLINEで家族に伝えたところ、娘が 「おめでとう以外は言いたくなかった」 と泣いたそうです。 父ちゃんがんばるよ。。。


今回の軌跡(DESC)

Event 

See also