isucon13 参加記(25000点くらい)
isucon13 に参加しました 忘れないうちに備忘的な記録を残そうと思います
zenn か何かに書こうかと思ったけど、そんなに有用な話でも無いので久しぶりにここに書きました
TL;DR
- isucon本読んでモチベが上がったので出てみる、なんやかんやあって結局一人参加
- 最終ベンチが 25000 くらい、再起動試験に通ったかは知らない
- やったのはほぼアプリ + DB改善のみ、サーバー一台構成のままだし dns は何もしてない(できなかった)
- 最後に EC2 落としてから git に commit はしてたけど push してなかったことに気づいたのでソースコードが残っていません、悲しいね
やったこと
免責:ソースコードと commit log を紛失したのでやったことと得点は大体の記憶です、100%一致してないと思います fgprof のスクショがちょこちょこ残っていたのでこれをメインに書きます
最初
- とりあえず fgprof と slow query log を入れます
- nginx, alp 周りは面倒だったのでいっか〜ってなって結局最後まで入れませんでした (fgprof で何となく分かるしね(ほんまか?
getLivestreamStatisticsHandler
周りの N+1 改善, index 貼り
(これ今他のと見比べたらちゃんとログ取れてるかだいぶ怪しくないか?)
まあこれを見て getLivestreamStatisticsHandler
が明らかに死んでいると判断したので、コードを見るとどう見ても N+1 で ranking を取得しているのでとりあえずこれを潰します
ついでに user の方もどう見てもN+1だったので潰します
業務で鍛えたSQL力😤
あとは slow-query log を見ながら userId
とか livestreamId
周りとかに INDEX を貼ってだいたい 10,000点超えるくらい
fillLivestreamResponse
周りの N+1 改善, index 貼り
統計を潰すとこのへんにボトルネックが移ってそう、 fillLivestreamResponse
が怪しそう
よく見るとここもやっぱり N+1 になっている (同一の Livestream の comment を取得したあとに comment ごとに Livestream を取得し直している) ので潰します
これで 16,000~17,000 くらいまで行った気がします。この時 20 位くらいに一瞬入ってて嬉しかった(こなみ)(isucon はベンチ fail した時に 0 点になるので途中順位は全く意味ないんですが)
icon 周りのキャッシュ
sha256.Sum()
とかにボトルネックが移ってるな〜という気持ちになります。レギュレーション読んだけどこれが何に使われているかは結局よく分からなかったです、とにかく計算が遅いらしい。
なんとなく user 数はそこまで増えないっぽかったので (これは嘘で高速化していくと最終的にはちゃんと user regist も飛んでくるらしいという話?だがそこまで行ってない) go なので mercari_go_isucon.md · GitHubを参考にさせて頂き雑にインメモリキャッシュをします。 ついでに icon の画像取得も DB だと IO が重そうなのでインメモリキャッシュをしてしまいます。(nginx から静的ファイル配信すればいいんですが、なんかうまく行かないな〜となりました)
これで 21,000 ~ 22,000 点とか
最後
このへんまで来るとアプリケーション側で目に見えるボトルネックはパッと見なさそうになったので、 ベンチ実行時にタイムアウトと言われてた API を見てみて細々とした改善を入れます
- ngWord の登録時のコメント削除周りにあった N+1 っぽいのが潰す
- ngWord 判定をなんか DB でやってるのをアプリケーション側に
- user 取得時のもろもろのクエリを一本化
- reserveLivestream で不要なクエリを削除
など、最終的にログを全部オフにして 25,000 点くらいで終了
反省 & 感想
- 昔出た時はまじで自分は手も足も出なかったが、Isucon本読んだおかげで簡単そうな部分は順当に改善進められて良かった
- 特に計測 -> 改善のサイクルを回すことを意識したおかげでちゃんと正の進捗を生めた、昔は勘でやっていたので改善が効いたり効かなかったりの運ゲーをしていたので
- DNS なに?
- powerdns の thread とか増やすと 水責めレベルが上がり、DNS解決数は増えるがスコアが落ちて何?ってなってた
- subdomain が random で cahce hit しないし、出処も同じ?っぽいので正しい対処方法がよく分からなかった
- サーバー複数台構成はちゃんと練習しておけ(完全に忘れており、今からやっても間に合わんかとなりました)
- GitHub に push しておけ