(2024/09/22記) 去年のISUCON13に参加したときの記録が下書きのままになっていたので、いまさらですが公開します。
同期の @homirun @yukun と一緒に、ISUCON13に参加しました。
結論はこれ。
くやしい、おもろい!
— やんまー (@yammerjp) November 25, 2023
最後のスコアは1万点にギリギリ届かず満足できないけれど、何もわからんという感じにはならずやることはたくさん見えていたので、次回(が開催されるならば)ご期待ください!
やったこと
前日まで
夏頃から、毎週1時間くらい業務後にあつまって練習していた。ISUCON本を読んでprivate_isuをいじってみたり、APMを入 れてみたり。1時間でできることは限られているけれど、なんもわからんというところからちょっとずつ全体感をつかむこ とができた。
前々日には、本番の半分くらいの時間でISUCON12の予選問題を解いた。ベンチマーカーのCLIの引数にIPアドレスを指定できることに気づかずベンチマーカー内の名前解決に困ったり、初手でSQLite -> MySQL移行をしようとし詰まったり、ほぼ 何もできなかった。この経験はおそらく当日に生きていて、この日に先にハマっておいたおかげで、当日無理にロードバランシングに手をつけずに済んだ感がある。
前々日と当日は、渋谷某ビルの(勝手)サテライト会場で開催した。物理的に集まってホワイトボードに構成を書いたりしながら同期的に進めるのは、結構楽しさがあった。
当日午前
当日の出来事は以下のような感じ。(全部覚えていないので、自分以外のメンバーがやってくれたことは書かれていないことも結構あると思う)
- 初手は競技とアプリケーションのドキュメントの読み合わせ
- 次に、Cloud Formationで起動してそのままベンチマークを一回回してもらった
- 最初はMySQLの中身をdumpして保全したりした。(これはあんまりいらなかったかも)
- Datadogをさくっと導入してくれたので、一番上に出ていた
/api/user/:username/statistics
のうち、ランク算出のN+1を直す。GROUP by user_id
でSUM/COUNTするクエリにして、一番重そうなところを直したらボトルネックが他に移った。N+1がまだ残っているのを横目に見つつ、呼ばれる回数が少ないエンドポイントなので他を優先するために無視。 - 裏ではPowerDNSをやめたりMySQLを分離したりタグ周りのN+1を潰したりしてくれていた
当日お昼頃
- コードをローカルで編集しても試しづらいので、途中で占有できる実行環境が欲しくなり、Cloud Formationをつかって競技外のインスタンスを開発用に用意してもらって、そこで自分だけのVMを手に入れた。
- このあたりでサブウェイにみんなでランチを買いに行った気がする。エビアボカドを頼んだ。フットロングにはしなかった。
- Datadogの合計実行時間の長いクエリを上から眺めて、貼っていった。
ORDER BY created_at
がいくつかあったけど主キーがAUTO INCREMENTだったから主キーでソートすることにしたりした。 - ここまでのVM分離とN+1とインデックス追加で10000点ちかく行っていた気がする。(合ってるっけ) このあたりまでは結構順調だった気がする
当日夕方
/api/livestream/:livestream_id
のN+1がひどいので直そうとしたが、バグらせてしまって元に戻すなど。ベンチマーカーがエラーを吐く状況をつかめなくて、再現できずに結局最後までこの変更を入れることはできず。- 裏では重そうな箇所をメモリでキャッシュする戦略を試してくれていたっぽい。詳しくはみていないがキャッシュのパージタイミングがむずそうっぽかった。
- MySQLのパラメータチューニングや、DNSとアプリのVMの分離で、+1000点弱あがっていそうだった
振り返り
よかったこと
ローカルに開発環境を用意しようとしなかったのは良かったと思う。しゅっとできないと時間が食われてしまうので。
チームメンバーが自分ができないことをバンバンしゅっとやってくれてとてもありがたい限りだった。yukunがDatadogをさっと入れて、なんなら競技時間中に全然わかっていない私にDatadogの使い方を説明してくれたり、homirunにミドルウェアまわりを完全に任せっきりにしていたが勝手にいい感じにしてくれていたり。
Datadogが最強すぎて、スロークエリログもエンドポイントごとのalpでの解析もみずに、Datadogみておけばいいじゃんという感じだった。これのおかげで、次何やればいいかわからんみたいなことにはならずに「明らかにここらへんをやったほうがいい」がわかる状態になれた。
改善したいこと
設定ファイルやスクリプトなどは持ち合わせていなかったので、viキーバインドでないbashターミナルや、コミットメッセージを入力するときに起動するnanoに困ったりしていた。共有環境にdotfilesをそのまま流し込むと他の人も影響を受けるので、自分だけ効くような初期化スクリプトを用意しておく方がいいかも。
明らかにN+1なのはすぐにみつかるけど、それをユニットテストもローカルの開発環境もない中、短い時間でコードを一気に書き換えきるみたいなことに慣れておらず、なかなかうまく直せなかった。
コードを書いてから動作確認までのフィードバックループが長くなりがちなので、たとえばGETの正常系の動作確認などでもいいから、簡単なものはさっと動作確認できる環境を整えておいた方が良かったのかも。変更前と変更後で同じcurlコマンドの結果が一致することを確認する、みたいな。
後半に取り組んでいた改善は結局入れられなかったので、バグらなそうな変更方針を建てて、走りきれそうな範囲を決めて直す、というふうにしたほうがよかったかもしれない。全部直すのは時間的に絶対無理なようなので。
おわりに
とてもおもしろい会を開催してくださった運営の皆様に感謝します。一緒に戦ってくれたチームメンバーに感謝します。くやしい、そして楽しかった!