ISUCON 7 予選2日目に @yteraoka, @ryoryoryohei とともに m3d3v チームとして ISUCON 初参加してきた。
実は前から一度 ISUCON 参加できないかを考えていて、たまたま今年は予定を空けられそうだったので、 同僚に聞いてみたところ快諾いただけたのが始まり。 参加応募時の自分の事前知識でいうと ISUCON 4 くらいの"インフラだけでここまでできる"みたいな記事のインパクトが強く、 インフラできる人と参加出来る時点で自分は遊んでいてもいけるだろうと踏んでいた。 なので当日は Elixir 実装を作るぜーみたいな呑気なことを考えていた。 あと参加者全員子持ちで時間がないってのは共通認識だったので、あまり必死にならずに軽い気持ちで参加しました(ISUCON は普段通りやればいいって話もどこかで聞いていたので)。
1週間前くらいになってそろそろ何かしようと思い、ISUCON 7 予選攻略記事を読んでみるとインフラだけじゃなくアプリの対応も肝心、 それに予選参加チームが400チームもあるということで、相当厳しい戦いになるんだろうと、少なくとも何かしら準備しないとダメっぽいと意識が変わった。 とりあえず攻略記事に書いてあったことを何かしらやらねばーと思うものの時間がなくて、rack-mini-profiler を sinatra に組み込んでちょっと触るくらいしかできず。。。 前々日になってようやくランチ兼初打ち合わせをして、軽く認識合わせをした。 とりあえず自分がアプリ(Ruby 実装ができてたので Ruby)、@ryoryoryohei が DB 周り、@yteraoka に他インフラ周り全てとざっくり担当分けできてよかった。 ランチしてなかったら担当分けも曖昧なまま参加していたかと思うとそれなりに恐ろしい。
- オフィスの会議室を借りて3人集まった
- みんな忙しいから最初リモートを考えていたが、多分集まらないとコミュニケーション回りが厳しかった。集まっていて正解。
- コードバックアップ先は GitLab でプライベートにして対応
- コミュニケーション取りやすくするために一応 Slack を用意
- ホワイトボード
- おやつとか
- 11:00 セットアップなど(デュアルモニターは少なくともしておいた方が良い)
- 12:00 Ubuntu よく分かっていないので予習したりランチ
- @yteraoka が kibana 環境を用意してくれたりしてた
- 13:00 ban 食らって一瞬入れないものの、別のインスタンスからログイン
- 一通り中身を見て回る(予選マニュアル, アプリ, アプリコード, Puma 設定, db 中身, etc...)
- コードのバックアップとかは @yteraoka にお任せし自分はアプリをとにかくみる
- この時点で気付いたことは
- isubata は idobata からか!(気づくの結構遅れたのもあって最初のアハ体験)
sleep 1.0分かり易すぎるしダミー的なものだと思った- /icons をまずは何とかしないとダメ
- 最初のベンチは Ruby に切り替えて実施。他のチームが6000くらい出している中3500?くらいで凹む。でも言語は関係ないだろうってことでそのまま方針変えず進む。
- 13:40 ローカル環境構築しつつコード確認
- MySQL がなぜか動かなくなっていてかなり時間無駄にした。MySQL わからーん。
- 15:10 初コミット 4100
- image table の中身が結構重複していたので limit 1 つけただけ
- 15:20 @ryoryoryohei が DB 必要なところへ index つける 6739
- 15:30 sleep はダミーだろうなと思いつつ消さない手はないよねってことで消す 23161
- ここで一気に上がったので嬉しかったのだが、その後これがダミーだってことを完全に忘れてしまったのは良くなかった。sleep が完全に意識の外へ消えた。
- 16:10 MySQL connection 上限 151 に引っかかる
- なんで増えるの?ってことで close 忘れがあることに気づいて直す 29768
- 16:30 並行して作ってた画像作る対応を入れる 27539
- レギュレーションを勘違いしていて DB にある画像をなぜか /intialize で作っていた(一回作ってファイルにしておけばレギュレーション的に OK なのに気づかず。。。)
- 16:40 Puma のスレッド増やすのと select * で無駄なところを直す 25653
- 16:55 profile での画像作成時にファイルにも吐くようにする 27466
- 17:05 nginx でそもそも画像キャッシュ 31057
- これが思ったように上がらなくて、なんでやーとなってた。が、自分も自分のことやらねばってアプリに集中しすぎてしまった(焦りもあったと思う)。
- 17:06 @ryoryoryohei が
random_string遅いのを SecureRandom へ 26514 - 17:30 @ryoryoryohei が N+1 系をガリガリ削り出す スコアメモ忘れ。。。
- 自分は次に遅い fetch をなんとかする方向へ
- パレートの法則で遅いやつから順次対応って感じでやってたけど、これは適していなかった。レギュレーションにも fetch じゃなくて message で点数が上がると書いてあるのに js 側コードま でちゃんと読めていなかったのも敗因。。
- 17:37 @ryoryoryohei が message の N+1 を削除
- 17:48 fetch 改善のためにキャッシュにトライ、最初メモリに載せていたがこれは分散環境ですということで当然ベンチ失敗
- 18:10 バグ直したり
- 18:18 nginx でキャッシュすることにしたのでアプリ側の画像作成処理を削除
- 18:21 @ryoryoryohei が login 失敗時に session[:user_id] が更新されないバグを対応 確かスコアが上がった
- 18:30 @ryoryoryohei が thread local へ MySQL Client を載せる 33632
- 18:51 redis 周りの対応を fetch へ入れる、ところどころ間違っていて戻したり適用したり
- 19:30 ようやく redis fetch 対応を入れるが上がらない 27289
- nginx でキャッシュしているものが数秒以上かかるようになってしまい厳しい状況へ
- 35292
- 20:00 reboot したら大丈夫なの?ってのを確認していなかったので @yteraoka にお願い
- 再起動したら puma か何かおかしかったので確認しておいて正解
- 20:30 redis の初期化を入れる 45508
- ベンチもかなり振れ幅が大きい。ネットワークが調子いいかどうかでかなりブレていた感じ。
- 20:40 haveread を redis 化するものの 31044
- スコアが本当に悪いのか、ベンチのブレなのか、わからず対応を戻す
- 21:00 ラスト実行のスコアは 33471
最終スコアの 33,471 でフィニッシュ。予選通過ならず。。。最初軽い気持ちで参加決めたくせに、何だかんだ負けるとかなり悔しい。
- 落ち着く
月並みだが改めて振り返ってみると本当にこれ。とりあえず自分落ち着けという感じ。特に以下。
- MySQL 環境ではまりすぎ
- 焦ってメモリストアでキャッシュ実装するとか
- スコア計算周りをちゃんと理解して読んでいない
- アプリ側みるといいつつ js をほとんどチェックしていなかった
- /icons で問題が解消できていない件を完全にお任せにしちゃって意見もほぼ出せず、深堀もできてなかったこと
- プロファイラ
前々日くらいに NewRelic か X-Ray 入れるって話になっていたが結局時間なくて何もせず。 プロファイラを入れておけば効果があったかどうか一目瞭然なので、ベンチがブレてるかどうかに惑わされてリバートもなかったように思う。 あとは当てずっぽうでこれをやるってのも少なくなっただろうな。 @yteraoka が Kibana 環境作ってくれてたので、正直それでかなり救われた。
- 休憩時間
作業に熱中しすぎて大事な考える時間が取れてなかった。 お互いの疑問に思っている点を時々周りに聞いてフィードバックもらったり、解消したりってのを、時々意図的にでも挟めばよかったかなと。
運営の皆様お疲れ様でした。快適な環境に、快適に実行できるベンチで、初参加でしたがかなり楽しく問題に挑戦出来ました。
そして ISUCON はチームで参加するって意味が存分にわかりました。一人ではとても厳しい。仮に一人で対応したら1万くらいいっただろうか?ひょっとすると ban されたところで死んでたかもしれない(笑) 今回担当分けも自然といい感じにできたおかげで、環境周り、DB 周りはほぼお任して相当楽をすることができ、完全にアプリ対応に集中できていた。 この辺りは普段の仕事でもお互いの専門性を生かしながらやっているので、いつも通りといえばいつも通り。仕事の環境がいいってことも改めて確認できたのは良かった。
今回結構反省点があったので次の機会もぜひチャレンジしたい。と思いつつも家族にも迷惑かかっちゃうのでこればっかりは状況次第かな。 ちなみに悔しさのあまり電車を乗り過ごすという実績を解除して、余計帰りが遅くなって家族に迷惑をかけたりもした、ツラい。