ISUCON8の過去問やったので感想書くべし
ISUCONやったらwrite up 書けってじっちゃんが言ってたので書きます。
ISUCON8やってない人はナンノコッチャだと思うのでブラウザバック推奨です。
最高スコアは2万6000点ほど。 一応学生枠だったら予選突破ラインである。 (確かボーダー1万3000点)
とは言え、ガッツリ8時間やったわけではなく講義やバイトの合間を縫ってやっていたので時間は覚えてない。 8時間以上やってる気がする。
ISUCONについての説明は省きます。 知らない人はこの記事を見てみてください。そしてやってみよう!
事前準備
準備は大事ばい!ってばあちゃんが言ってたので、ISUCON用にプロファイルツールやNeovim, zshなどの導入スクリプトを準備しています。
今回はこれを流し込むだけで、とくにハマらずツールの導入ができました。 zshやneovimはボクの使ってるzshrc, vimrcをそのまま使っているので、チームでやるときは流し込まないほうが良いかもですね。
開始!
今回はひとりぼっちのISUCONでした。 (SOLOCONって読んでます)
なので、サーバーにSSHで入ってゴリゴリコードを書き換えていく方針にしました。
まずは、アプリケーションを把握しないといけないのでブラウザから一通り触りました。 その後、DBのテーブル構造だったり、テーブルごとのデータサイズ、indexなどを調べ、目に見える位置にテーブル構造を貼ります。
こうしておくと関係がいつでも見えるのでバッチグーです。
次に、alpやpt-query-digestでログ集計ができるようにh2oとmariadbのconfigをいじります。
h2oのアクセスログは出力できたのですが、mariadbの方は出力できませんでした、、、コンソールから直接設定したら行けた。
終盤には分かったんですが、my.cnfのパーミションが不適切で読み込まれてなかったみたい、、、
Warning: World-writable config file '/etc/my.cnf' is ignored
このようなwarningがずっと出ていたみたいですが気づいてなかった、、、 thread cacheやら、buffer sizeやらを設定していたおかげで、my.cnfのパーミッションを変えるとスコアがそこそこ上がりました。
alpで集計ログを見ると /
や/api/user/:id
が遅いことがわかります。
で、該当コードを見ると、めちゃんこにN+1 クエリが散りばめられているではないか! その中の一つにgetEventという関数があり、これは色んな所で使われているので、ここを最初に修正することにします。
これでスコアが 6,7000点になりました。 言い忘れてましたが初期スコアは500でした。
次にgetEventsの修正に取り掛かります。 この関数はほんとにヤバくて、getEventは N+1だったんですが、getEvents内のループでgetEventを更に呼んでいるのです。
ひゃーこりゃ遅いわ、、、 ってことで修正に取り掛かります。
また、indexの効いてないクエリがいくつか合ったので、indexを貼ります。 一番効果があったのは reservationsテーブルに対する、event_idとcanceled_atの複合キーです。
getEventsとreservationsに対するindex付与で2万6000点に行きました。
ここから何をやってもだめ
はい。ベンチマーカーがfailし始めるようになりました、、、、
結果として、これを修正することはできず神に祈りながらベンチを回し続けました。
しかし、その後2万6000を超えることはなかったですが。
sheetsテーブルに対するクエリは多数あり、またinner join sheetsなどもあります。 sheetsは特に更新がないマスターデータだったため、プログラムで処理するようにしました。
その結果スコアが上がると踏んだのですが、上記の通り、微動だにせず、、、
何なら下がり続ける。みたいな状況でした。
おわり
ほかにもいろいろやったのですが、結局スコアは上がらず、、、、 2万6000時点からいろいろとクエリを減らしたり、N+1を多数減らしなのですが、ここまで上がらないとは思いませんでした。
スコアが全てなのですが、確実に速くなっていると思うんですけどね〜、、、
悲しいかな、ISUCON8は惨敗でした。
ですが、楽しかったです。 問題作成者様まじでありがとうございました!