ISUCON8の予選を学生枠で突破しました

どうもこんにちは。
チーム(´・ω・`)の(´・ω・`)担当(たぶんアイコン的にそう)のnagatechです。

Iikanjini Speed Up CONtestことISUCONの予選に同じサークルのmasutech16takashi_trapと参加したので参加記を書きたいと思います。ブログを書くまでがISUCON8予選らしいので。
3人ともISUCONは初参加です。

結果だけ言うと、学生上位12チーム枠で本戦出場が決定しました。
偶然に偶然が重なった形での予選突破ですが、素直にうれしいです。

ISUCON予選参加記

自分は主にインフラ担当だったので、アプリ側の細かい挙動とか分かってないです。
ご了承の上見ていただけると…

ちなみに他の2人はブログ持ってないそうです。悲しい…

前日まで

6月くらいに1度、大学のサークル内でPisconという名前で部内ISUCONが開催されて、それに参加しました。
詳しいことはとーふとふのブログに書いてあります。(ちなみにとーふとふは予選1日目3位で予選通過したNaruseJunチームのメンバーです)

その時の得点が近かったmasutech16とtakashi_trapでチームを組むことになりました。

予選2日前に1度集まり、方針の決定と本番用プライベートリポジトリの作成、予選開始前にできそうなこと等々をやりました。
takashi_trapとmasutech16がGoの鬼なので、実装はGoで行くことにして、masutech16とtakashi_trapはアプリ担当、自分はインフラ担当でいくことになりました。

予選1日前は、ISUCON7 オンライン予選 関連エントリまとめにまとめられている記事を上から順に全部読んで、予選での戦い方などをおさらいしました。
複数台構成のことを何も考えてなかったので、不安で仕方なかったです。

その後はConoHaのISUCON7予選イメージを使って初動の練習して破壊して…を5回くらい繰り返しました。

当日

一番難しいと言われている(?)起床はうまくいきました。

予選は3人で大学の講義室に集まってやると決めていたので、大学に向かいました。
途中で腹痛に襲われたり、ノートPCの充電器を忘れてることに気付いて取りに戻ったりと謎の不運に襲われてたら予選開始に間に合わなそうになりました。ギリギリ9:55にたどり着きました。

10:00 競技開始

(↑競技中、最初で最後のツイート)

当日マニュアルを読むのは大事だということは分かっていたので、まずは3人で当日マニュアルの読み合わせをしました。
最後のスコア(と追試に合格するかどうか)で結果が決まることを確認しました。

とりあえず初期実装(Perl)のままアプリを見に行こうとしたのですが、なにかのエラーで見れないようになってたのを覚えています。
どうせGoに切り替えるので無視することにしました。
原因はMySQLへのコネクションがタイムアウトしてることだったらしいので、初回のベンチはfailでした。

初動は自分とmasutech16が各サーバのssh設定、takashi_trapがソースコードをgitリポジトリに含めたり実装をGoに切り替えたりといった感じでした。
ここら辺の初動は練習してたのでスムーズにいきました。

10:29 正の点数を獲得する

Go実装での初期スコアは1347点でした。

ここでやっとどういうアプリなのかを見ることができたので、自分は実際にアプリを触ってみてどういうアプリなのかや、DBのテーブルを確認してそれを共有するということをしました。

「torb」という名前のイベントのチケット予約サイトといった感じのアプリケーションでした。(元ネタは東急シアターオーブって聞いたんですけど本当なんですかね…?)

masutech16はkataribe・pprof・myprofilerなどの計測ツールの導入、takashi_trapはWebサーバをh2oからnginxへの移行をやっていました。
3人ともh2oを触ったことがなかったので慣れているnginxにしようということが3秒くらいで決まりました。(競技終了後の感想チャット見てたら同じ人多くてちょっと笑った)

11:07 初期構築終了

nginxへの移行も無事終わり、アプリが正常に起動するようになりました。
また、他の2台のサーバのセットアップも終わり、どのサーバでもアプリが配信されるようになりました。(他の2台にはDBサーバがないのでこの時点ではアクセスしても500エラー)

ようやくアプリ側のチューニング開始といった感じでした。
masutech16とtakashi_trapにはアプリ側のコードを読むことに専念してもらい、自分は自動デプロイの準備をやりました。

11:31 自動デプロイ整備

サーバでnodeが動いたので、nodeでさくっとgithubのWebhook用のスクリプトを配置しました。(ほとんどmasutech16が事前に用意してくれていたのでそれをちょっといじるだけだった)

CentOSはデフォルトでfirewallが動いていて使うポートを開放しないといけないこと知らなくてちょっと詰まりました。

11:40 DBにインデックスを貼る

myprofilerで時間がかかってるSQL文を洗い出したので、そこを中心にMariaDBに接続してインデックスを貼りました。
経験上、インデックスを貼るだけでそこそこ点数が上がるはずだったのですが、まったく効果がなくてあれ???ってなりました。

これはGET /initializeでリカバリ用のinit.shが動き、そこでDROP TABLEしてテーブルを作り直すからだということをtakashi_trapが即座に気付き、アプリ側でインデックスを貼るようにしてくれました。

12:57 得点が跳ね上がる

masutech16とtakashi_trapがgetEventのN+1問題の解消、自分がnginxでfaviconとjsとcssのキャッシュをするように変更などをしました。

ここでベンチを回したら8738点で暫定全体3位、その5分後にもう一度ベンチを回したら13019点で暫定全体1位になりました。

このスクショ撮れただけでISUCON参加してよかったとその時は思いました。
(その6分後に追い抜かれた)

このあたりからたまにfailで0点が出るようになった気がします。

14:50 サーバを1台から3台にした

(自分が今回一番頑張ったところ)

複数台構成のWebアプリケーションを触ったことがなかったので、詰まりながらもなんとか3台構成でWebアプリケーションを動かすことができました。

具体的な構成は、プライベートIPアドレスが若い順に

  • DB
  • App + nginx
  • App

とし、2番目のサーバへのアクセスをnginxで2番と3番に振り分けてDBは1番に接続といった感じにしました。

途中2番のinit.shを書き換えたときにミスってDBのテーブル全部吹き飛ばしたときはマジでISUCON終了したと焦りました。リカバリに感謝。

点数は12000点前後が出るようになりました。もうちょっと上がることを期待してた。

この後はmasutech16が解析やコード読んでやばそうなところの発見、takashi_trapがひたすらアプリ側の実装、自分がnginxとmariaDBのチューニングといった感じで進めていきました。

(このあたりからちょっと焦りだして作業の記録が残ってないので曖昧)

15:30くらい failが多発するようになる

ベンチマークを回すと、GET /admin/api/reports/events/11/salesでid190000くらいの列がcsvに存在しませんみたいなエラーでfailすることが多発しました。
しかし実際にcsvを見てみるとちゃんとその列のデータは存在してたのでうんうん唸ってました。

アプリがそこそこ速くなったことでレポートを生成してる間に予約が入ってしまって不整合が生じることは分かったんですが、解決策が思いつかず、時間だけが過ぎていきました。

17:00くらい 再起動試験

とりあえずfail多発問題は置いといて別な部分の改善とかを進めて、17時くらいに事前に打ち合わしてた通りにサーバの再起動をしました。

ベンチマークを回すと見事にGET /initializeの時点でfailしました。
どうやらサービスがenableになってなかったのが原因でこのままいけばfailで失格だったので危なかったです。

最後の1時間、masutech16がfail問題を考えて、takashi_trapがnicknameをセッションに乗せるようにしてた(バグったので泣く泣くrevertした)なか、自分は何もできることがなく、ただfailしないように祈ったり、踊ったりしてました。
強いて言うなら自動デプロイを止めて、githubにpushがあったら3台のサーバに手動でデプロイしたことくらいしかやってないです。

17:50 ベンチマークガチャ

最後のスコアで結果が決まるので、いいスコアが出るように祈りながらベンチマークを回しました。
まだたまにfailすることがあったのでめちゃくちゃ怖かったです。

本当はここでログとかを切っとくべきだったんですが、みんな焦って忘れたままベンチマーク回してました。(というか自分が祈りをやめて作業するべきだった)

最終提出スコアは13153点でした。

18:00 競技終了

全体のスコア推移から、追試に合格すれば学生枠で本戦行けるかも??と思いながら予選が終わりました。
終わった後は同じサークルで予選に参加した人たちと感想戦をしました。

NaruseJunは1日目上位3チーム枠でサクッと本戦出場を決めててすごいなあと思いました。

結果

学生枠で本戦出場が決定しました!

複数の学生チームが上位になった影響で繰り上がり繰り上がりでの予選突破ですが、初めてのISUCONで本戦出場決定(しかも大学の同じサークルから2チーム出場)という快挙を成し遂げたので嬉しいです。

この記事を書きながら、他のチームの方々のブログを読んでるのですが、同じような改善をしてても点数が倍以上違うので現場にいる人たちとの経験の差をひしひしと感じました。読むだけでも勉強になります。

自分の力不足を実感した学びの多い予選でした。

あと1ヶ月、自分になにができるかを考えながらISUCONの本質である「勝つこと」も意識して本戦に向けて勉強していきたいと思います。

(せめて最後1時間祈る人にならないようにしたい…)