ISUCON 9予選の反省
ISUCON 9の予選に敗退しました。 前回のISUCON 8では同じように予選敗退して記事は書かなかったが、今回はよくない動きをしてしまったので戒めとして反省記事を書くことにした。(感想も書きます)
本番前
ISUCON今年はどうしようとTwitterでつぶやいたところ、ISUCON 6や7のときのチームメンバー(mot, syusui)が声を上げてくれたので、チーム3年目として参加することになった。
今まではrubyで参加していたけど、goで参加してみないか?とmotさんから提案があったのでgoで行くことになった。 goは一切書いたことなかったので、A Tour of Goを一通り読んでISUCON 8の過去問を触って、という感じで1週間の夏休みを使って勉強した。 これでISUCONをやるには問題ないぐらいにはgoが書けるようになったと思う。
本番やったこと
- pprofを使えるようにした
- 新着アイテム、カテゴリ別新着アイテムの並び順をredisから取れるようにした
以上という感じで、全然取り組めなかった。 pprofとかで遅そうな場所を把握した時間が12時ごろ、新着アイテムの並び順をredisから取れるようになったのが15時半ごろ、カテゴリ別新着アイテムは17時ごろに実装完了した。他に何もできなかった。
カテゴリ別の新着アイテムの取得の部分が遅いと気づてコードを見たときに、N+1クエリがあったのと一覧取得クエリに複数のIN句とOR条件があったのに気づいた。 一覧取得クエリはindexを張ったりIN句やOR句をなるべく使わないように修正する手もあるなと思ったけど、redisのsorted setを使えば一気に解決できていいのでは?と考えてそうすることにした。 この判断が本当によくなかったので大反省をしている。
やったことに対する反省点
- 実装に時間がかかりすぎてしまった
- 1, 2時間でできるだろうと思っていたけど、その2倍以上はかかってしまった
- 練習時には無限に時間がある中でredisを使った実装も試してたので、サクッと行けるだろうと過信してしまっていた
- そのため自分は他の部分に着手できなかった
- ときには大規模な改修も必要かもしれないが、競技時間が短かったり改善するとボトルネックが別の場所に移りやすかったりなどの理由から、基本的には短時間で試せる改修を積み重ねて行くほうがいいなと思った
- 時間がかかった割に効果が薄かった(と思う)
その他の反省点
- APIのアクセス傾向やレスポンスタイムをあまり把握してなかった
- 結局DBのindexは全く追加してなかった
- slow queryは出していて最初ちらっと見ただけで何もしてなかった…
- 購入周りはロックで詰まったりするだろうなと薄々考えていたけど何もできなかった
その他感想
- キャンペーン機能でアクセス数をこっち側で制御できるのはおもしろいなと思った
- 講評の記事を見ると初出ではなかったらしいので過去問対策不足だったかも
- キャンペーン機能の数値を変えるとログインの負荷が一気に上がることに気がついたのが後半だったので、今後同じような仕組みがあったら早めにいろんな値で試してみたほうがいいなと思った
- Go Modulesよかった
- go初心者でも依存モジュールのインストールに全然躓かなかった
- bcryptの負荷が高かったのが驚いた
- ログインでこんなに詰まるものなんだと驚いた
- ログイン専用のサーバに分けて他の処理に影響が出ないようにすることは学びになった(競技中には対応できなかったが)
- ISUCON 8の本戦で同じような問題が出ていたことを知って、これも過去問対策不足だったなと思った
- ベンチを回せば回すほどパスワードのハッシュを更新できるのはどうなんだろう…と思ってしまった
- 椅子が売れた数がポイントになって、椅子が売れるようにある程度調整してもいいというルールは実際のサービスっぽくて面白いなと思った
- その反面、スピードアップコンテストとはちょっと違ってきている気も…という風にも少し思った(文句はないです)
- 機能が盛りだくさんで難しかったけど面白かった
- 商品の出品から決済、発送まで一通り機能があるのがすごいなと思った
- 決済や発送周りはちゃんと外部APIとして用意されていて気合を感じた
- 次回があれば今度こそ本戦行きたい…