🦁

ISUCON13に参加して20位でした

2023/11/26に公開

https://isucon.net/archives/57993937.html

チーム「なんかいい感じではやいやつ」で最終スコアは91,400点でした。
順位としては20位で、30位入りを目指していたので達成できてよかったです。

また、不整合エラーなどに苦しみながらみんなでベンチを回しまくっていたらfail回数が多かったということでTVer賞をもらえました。

今回初参加でしたが、チームメンバーに誘っていただいてアプリ担当(のうちの1人)として参加しました。

当日まで

何回か過去問を解く練習会をやりました。
傾向と対策だいじ

当日

何も記録をとっていないので、記憶頼りです。

-10:00

起床チャレンジにみんな成功したのでちゃんと9時に集合できた。
配信見ながら準備などをする。

10:00-10:30

開始早々「PowerDNSって何…???」でチームがざわつく。
初回ベンチやって確か3000くらいだったはず。
アプリマニュアルを読み込むなどした。

10:30-11:00

初手の作業として、SQLのログを見てindexを貼る作業をメインでやる。
インフラ担当のメンバーがMakefileの準備とかKataribe, MySQL Logの設定とか色々やってくれていたのでそれを待ちながらコードも軽く目を通す。

11:00-13:00

Kataribeのログを見ていると/iconが遅いのがわかる。
マニュアルに、conditional GETしてもいいよってそういえば書いてあったしそういうことか〜〜〜になる。

とりあえず、画像のバイナリをそのまま突っ込んでいるのが色々不味そうということでiconテーブルにhashカラムを追加して、アイコンのアップロード時にhashを計算して一緒に格納するように。
(iconテーブルは初期データがないので初回の計算とかも不要で楽だった)
ちょっと詰まりつつ、12:00くらいに大体作業が終わって確認するも3xxのレスポンスが増えていなくて「なぜ???」となる。

チームメンバーと相談して、DB明らかに重いしDNS部分を切り離せるからアプリ1台のDB2台構成でいいよね?ということになる。
iconのハッシュが重いの嫌だなあとなりグローバルキャッシュを入れたりする(ただ、これは後に問題を引き起こしたりして悪手だった)

その後色々見ていると If-None-Match ヘッダーはダブルクォート付きで値が振ってくることに気がつき、見落としてた〜〜〜!!!って言いながら直す。
この辺りで10000近いスコアになっていた気がする。

13:00-14:00

またKataribeとSQLのログを行ったり来たりして、livecomment周りが重そうだったのでng_wordsの判定をSQLではなくコードでやるようにしたりなど。

N+1がかなりあるのに気がついていたが、割と込み入っていてめんどくさいな〜〜〜でこの時は放置した。

14:00-15:30

このあたりでベンチが落ちたり不整合を吐いたりしていた。
原因の一つとしてキャッシュがちゃんとクリアされるコードになっていなかったりミスがあったりでそれを直したりなどしていた。

(チームメンバーがDNS部分を切り離す作業を始めていたが、エラーに見舞われたりキャッシュの問題でうまくいかなかったりということがあったみたいだった(あまりわかっていない))

また、rankingの計算もかなり重そうだったのでN+1を解消したりしていた。
livestreamsとの無意味なINNER JOINもあったのでそれを剥がしたりもした。

多分このあたりでスコア20000くらい?だったような記憶

15:30-16:30

このあたりで、ベンチが「仕様違反」でflakyに落ちたりなど問題が見え始めて少してんやわんやした。
icon hashのオンメモリキャッシュをとったりしていたの、あんまり良くないのではないかになって結局剥がしたりもした。

APIとしてはlivecommentやreactionsあたりが重くなっており、まあ流石にN+1ですよね〜〜〜となり重い腰を上げて解消したりした。

色々あって30000くらいにはなった気がする。
アプリとDB分割の方針が立ったみたいで色々やっている横目で、1インスタンスでも30000くらいは出ていた気がするので30位入賞も結構現実的かも?などの話をした。

16:30-17:30

予定通りアプリ1台とDB2台(DNSとそれ以外)に分割して、ちゃんと整備してベンチしたらスコアが60000くらいになる。

ここでさらにN+1の修正などをして一度67000のスコアが出るも、設定に手を入れ始めてスコアが30000くらいまでに一気に下がってみんなで焦る。
ベンチを回して色々試した結果、nginxのkeep-aliveの設定を入れたことが原因であることを突き止めるが、これに気がつくのにかなり時間を取られた。

その辺りのエラーを修正して80000程度まで上がる。

17:30-18:00

ベンチで「仕様違反」というエラーが何回かに1回出て、いきなりスコアが80000から10000に落ちたりしてさらに焦る。

色々調べて、DB上でエラーが出た時に、エラーを握りつぶしてfallbackImageを返していることに気がついて急いで修正などをする。
(このDBクエリは通常エラーにはならないが、負荷をかけている関係で後半にdeadlockエラーが出るケースがあり、そういったケースでうっかり誤ったレスポンスを返していることによるものであったっぽい。)

色々直して90000くらいになる。
再起動試験やる時間ないーって言いながらタイムアップとなった。

18:00-20:00

結果発表配信をみんなで見る。
TVer賞を貰えたので、どうも30位には入ってそうだねーという話をしていた。

また、追試で失格にならなかったのが個人的にかなり安心した。

当日の振り返り

PowerDNSとか何もわからないーって言いながら結局無視したが、普通に無視していてもチューニングには支障がなかったので、半端な知識で突っ込むよりは正しい判断だったと思う。

後半、N+1の解消でスコアがバンバン上がるみたいなやつが体験できて楽しかった。

一方、flakyなベンチの対応を後回しにした結果最後の方でヒヤヒヤする場面が多かったのでそこは良くなかったと思う。もっとアプリのログを眺める作業を真面目にやるべきだったかも。

また、最後の方で2箇所くらい同時に変更してベンチしたらスコアが下がる→原因究明に時間がかかるといったことがあったので、最後の方ではもっと慎重にいくべきだったなというところも反省。

全体的に時間は結構足りなかったが、途中にベンチの調子が悪く何もできない時間もそれなりにあったので、それを考えるとトントンくらいかも?
N+1を結構残してしまったので、あと30-45分くらいあれば10万点は取れた気はするので少し残念だったかも。(ただ時間があっても全員平等にスコアが上がりそうなので順位は変わらなさそう)

全体の振り返り

練習会のおかげでだいぶ自分でも動きがわかったので、やってよかったなと思った。
一方で、今から思うと練習の時は1万点-5万点くらいの動きを練習することが多く、5万点超えてからの動きを練習する機会に乏しかったなと思ったので、次もしやるならその辺りを中心にやるべきかもしれない。

最後に、初参加ですが楽しかったので誘っていただいたチームメンバーには感謝。

Discussion