平常運転

アニソンが好き

過去記事とかは記事一覧で見れます

ISUCON10に参加して予選敗退しました

しました。

isucon.net


我々のチーム "できの悪いウォーターフォール開発" は予選敗退となりました。最終スコア(かつベストスコア)は1320点くらいです。

リポジトリはこちらです:

github.com

敗退はめちゃめちゃ悔しいし無念な思いですが、非常にやり応えがあって良い意味で ISUCON らしい素敵な問題でした!!!!多分文末にも改めて記しますが、これだけの大規模となった今回の ISUCON 予選を運営されたスタッフの皆様には本当に感謝しています。ありがとうございました。

以下は問題のネタバレを含むので、もし問題に関してノータッチでいたい方はここでお戻りください。
また、疲れていてかつお酒を飲んだ状態で書いているので支離滅裂だったり不正確な可能性もあります。後で素面に戻ってから追記したり修正するかもしれません。

スペーサー

うっかり視界にネタバレ部分が入らないように、スペーサーとして前日の晩ご飯に食べたやよい軒味噌カツの写真をお届けします。

f:id:astj:20200913010907j:plain

f:id:astj:20200913010907j:plain

そろそろいいですかね。いきましょう。

問題概観

おもいっきり DB ヘビーな問題でした。直近で予習した ISUCON9 予選がめちゃめちゃアプリケーションの CPU が支配的だったので、その記憶が新しいまま挑んだので、最初にベンチマークを回したときにほとんど MySQL に CPU が持って行かれるのにはちょっと焦ってしまいました。実際最後までアプリケーションが乗ってるサーバの CPU を使い切ることができませんでした。

おおまかなムーブ

  • 開始が遅れるということで朝からビールを飲む
  • ドキュメントを読んだりアプリケーションの振る舞いを見つつ、事前に用意した最初の1時間でやる手順書を元に3人で準備
    • Go 実装でやりました
    • どこを上げるとスコアが上がりそうかの確認
  • 序盤のあれこれ
    • Nginx で bot を BAN
    • MySQL の CPU で当たってることを確認して、ひとまず DB サーバを別ホストに分離
    • NewRelic 導入 (あまり活用できなかった)
  • 1時間〜おきくらいに様子を共有しつつ、おおまかに2ラインで変更を進める
  • 終盤バタバタと変更しつつ、終了数分前の計測でベストスコアが出てそこでフィニッシュ
    • MySQL の slowlog を切ったことで DB サーバの CPU がよく回るようになってスコア伸びたのかな〜と想像しています

ふりかえり

予選敗退ということでどうしても反省が先に出てしまって、特に個人的には競技最終盤で入れようとした変更を入れられなかったことの悔しさが大きい結果となりました。全体の方針や作戦周りも後日振り返れば良し悪しどちらの感想もでてきそうなのですが今は疲れて出てこないということで、今思いつく個人的な反省ポイントはこのあたりです:

/api/chair/search の Redis キャッシュ導入失敗

github.com

/api/estate/search の SELECT クエリを Redis に逃がすのを 20:00 くらい (!)にやっていて、それは見事成功したのですが:

github.com

それを /api/chair/search に横展開するのを完遂できませんでした。実装を入れた直後は通ったのですが、その後の事前走行でエラーが頻発して、原因が突き止められないまま無念の revert 。
競技終了後に Pull Request を見返したところ見事にコピペの修正し忘れが残っていました:

github.com

まあ /pull/25 の時点でミスっていたこと自体はまあよくて(コピペして書き替えていけば当然ミスると思う)、折角 GitHub の Pull Request でやっていて、落ちついて差分を見返せば一発で気付けるであろう間違いだったので、それを気付けなかったというのが個人的には辛いな〜と思っています。これは完全に終盤のバタバタのせいで、仮に同じ変更を前半に入れていたならメンバーからコードレビューを受ける余裕もあったかもしれないし、少なくとも「うまくいかないから diff を眺め直そう」という行動は取れたはず、と思っています。実際は最終盤だったので、ベンチ落ちる!じゃあもう revert します!!!という感じの行動しか取れませんでした。

データベースの垂直分割(estate と chair の別ホスト化)の失敗

github.com

mysqld が CPU を食い尽くしていて、 estate と chair を JOIN したりトランザクションで一緒に更新するクエリがなかったため、テーブルごとに別のサーバに割り振るという作戦。
今回もともと3台あったサーバのうち、1台がアプリケーションで1台がデータベースと割り振ったあと3台目を持て余していて、かつデータベースが CPU で当たっていたので、分割すると絶対にスコアが上がることはチームの中でも分かっていたのだけれど、クエリチューニングやインデックス張りで改善できるのではという方にチームの意識が向いてしまってなかなか着手できませんでした。
結局終了20分前頃になってから半ばヤケクソで取り組み始めて、一見コードは書き上げたつもりだったのだけど、どこかが悪かったらしく初期化をうまく通せないままに終わってしまいました。

これに関しては、まずコードの変更を完遂できなかった自分の不甲斐なさに悔しいのと、明らかにスコアの上がる取り組みであることに早い段階で気付いていたのに着手できなかったという作戦上の後悔の両面で後悔しています。

chair の検索にあと5分、データベースの分割にもう5分あればそれぞれ完遂できたのではないかと思っていて(後者は甘い見積もりかもしれない)、かつ、特にデータベースの分割をやれば結構スコアが伸ばせたのではという感覚を持っているので、もしかすると本選進出に噛めたかもしれないという気持ちが拭えず、自分の力不足に悔しいばかりです。

おつかれさまでした

ということで敗退でした。
ISUCON はこれで 5 本選出場 => 7予選敗退 => 10予選敗退となりました。

blog.astj.space

blog.astj.space

blog.astj.space

出場するたびに様々な学びと感情を得られる ISUCON には感謝してばかりです。今回も大規模な予選を遅くまで運営してくださったスタッフのみなさまに感謝ですし、一緒に出場した id:yashigani_wid:tkzwtks にも激しく!!!感謝しています。

本選出場される皆様はおめでとうございます。本選もがんばってください!!!!