ISUCON9 に参加し惨敗しました
お久しぶりです。 @bussorenre です。
前々から存在は知っていたものの、なかなかプライベートの予定が合わず参加出来なかったISUCON にようやく初参加出来ました!! 結果は、最終スコア2910 (初期スコア 2100くらい)で、まぁものの見事に惨敗です 😇
やったことの振り返りと、次回参加とかに向けての反省をば
チーム構成
会社のメンバーと組みました。と言っても普段業務で一緒に仕事をしているメンバーではなく、全く別のプロダクト開発に従事ししているメンバー、つまりほぼほぼ「はじめまして」のメンバーでチームを組みました。 メンバー全員にruby 知見があるので、使用言語はruby に即決。それぞれの担当としては以下の通りです。
- @Yoshimaru46
- @Miyamizu
- アプリケーションの改善
- @bussorenre
- 計測環境の整備やデプロイの自動化。ミドルウェアのチューニング等
@Miyamizu 氏が9月入社のメンバーで、@Yoshimaru46 氏がそのメンターということもあり、二人のペアプロ体制が最初に出来上がり、そこに私が乗っかった形のチーム構成です。
事前準備
チームが決まったのが8月最終日くらいだったので、事前準備にあまり時間を割けなかったのですが、就業後の時間等を利用し、物理的に集まって作戦会議等をしていました。
作戦会議で決めたことは以下のとおりです。
- 目標
- isucon に挑戦する(0次予選を突破する = 起床して課題と向き合う)
- 0点を回避する(必ずスコアが出る状態で終了する)
- 出来ることを確実にやる
初挑戦から優勝を狙いに行く強者もいますが、我々の実力的に(準備期間的にも)まずそれは難しいだろうということで、「わからないことに挑戦すること」を最も重要な目的としました。 雑に「絶対優勝すっぞ!!」とか言うと、圧があってかえって挑戦するマインドを萎縮させかねないので、「まぁ楽しもうぜ」ということを、共有しました。
一方で、出来ることは必ずやるようにしようという目標も設定しました。具体的には以下の事を必ずやるようにしようと事前に決めました。
- アプリケーション系
- index をしっかり貼る
- N+1問題の解消
- SQLの並列化
- 画像をバイナリでDBに持っているのをやめる
- 可読性低いコードをやめる
- 計測系
- スロウクエリの自動検出
- デプロイの自動化
- nginx のログをalp で統計する
- ミドルウェア
- nginx じゃないhttpサーバーが来たらnginx にする(わからないから)
- DBロックの調査
- Cache Control
- タイムアウト/キャッシュのの設定を適切に
- Worker数を適切な数に
また、alibaba Cloud という普段使い慣れないクラウドが舞台なので、確実にインスタンスを立ててssh 出来るようにする練習を行いました。
予選開始前から、解くべき課題を見つけるくらいまで
予選当日は9時過ぎくらいに会社に集合し、設営を行い、9:50分ごろから事前ブリーフィングを行いました。
まずは午前中にやることを共有し、私は以下のことを担当することになりました。
- 起動しているサービスを確認する
service --status-all
- 全ての情報をgithub に乗せる
- application (全実装)
- conf(nginx や mysql など)
- ↑で載せた情報をシンボリックリンクにする
- デプロイ自動化
- alp の構築
- 全体的に基本的なnginx.conf の見直し
私がこれらの基本的な設定に取り組んでいる間に、他二人のチームメンバーには課題を読み込んでもらい、N+1等、解決できそうな問題を発見してもらうことにしました。
諸々の準備が整ったのが11:52分。その頃には「どうやら /users/transactions.json あたりがN+1でヤバそう」という情報がアプリケーションコードからも、alp の統計からもう読み解くことが出来ました。
昼食。とりあえず寿司を発注する
メインイベント このあたりで、絶対集中力が尽きるだろうと思っていたのと、前日のチームが寿司を発注しているのをTLで観測したのを受け、「これはもう寿司頼むしかねーな!」という感じで頼みました。
発注から1時間足らずで届いたのにはびっくり。銀のさら様様です。
昼食を取りながら、お互い次に取り組むことを決めますが、どうもアプリケーション側にボトルネックが多いと判断し、私も午後からアプリケーション側を見ることになりました。 予定ではnginx の最適化とか、せっかくインスタンス三台使えるんだからDBとapp 分けるかとか考えていたのですが、アプリケーションを改善しないとインスタンス分離してもそもそもスコアが出ないだろうという判断の元決定しました。
午後:地獄のN+1潰し
このあたりで普段の業務を如何にライブラリや既存の仕組みにに乗っかかってるだけか反省することが多かったです…… 😇 join を使ってN+1を解消するのに結構時間がかかりました。普段如何にORMに頼っているかわかりますね。
あーでもないこーでもないと3人で言いながら /users/tranzaction.json
と /new_items
のアクセスを早くした頃にはもう16 時でした……。
「N+1潰したからベンチ上がるやろ!」と思い意気揚々とベンチを回すも、上述の「2910」までしかスコアが出ず 😇
改めてalpを確認すると、たしかにそこはかなり改善しているのですが、今度は /buy
のレスポンスが遅く、更に殆どのリクエストが4xx系のエラーを返していることに気が付きます。
このとき今更「そういえば、今回のスコアは商品の売上合計だったよな」ということに気が付き、よりたくさん商品を売りさばくチューニングをしなければ行けなかったことに気が付きます。問題の趣旨の理解が出来たのが16:30頃
必死にbuy の改善に取り組むも、「外部APIの仕様わからん」「なんでこんな403ばっかり返しているのかわからん」等と言ってるうちに18時となりゲームセット。 (※ 最後はポータルの不具合で18:10 まで時間が延長になりましたが…)
最終スコアは2910でした。
反省
大きく2つで、
- 焦らずもっと課題とドキュメントを読み込む事
- 環境構築系のスクリプトをもっと事前に用意しておけばよかった事
が課題でした。特に後者は、「本当に解くべき課題がなにか」を理解するのに遅れたという痛恨のミスです。
作問担当がメルカリということで、メルカリかメルペイっぽいアプリが来るだろうなーという予想を立てていたんだから、メルカリっぽいサービスを適当に作ってみるとかをしても良かったかなと思います。 この辺は実装経験が差をつけるかなと。
後者に関しては↑の課題理解をより早く行うためにある課題だと思っていて、構築系の自動化・高速化はもうちょっと備えていきたいかなという所です。
今回、チームメンバー全員がisucon 初挑戦という非常にフレッシュなチームで、個人的にはかなり楽しくさせていただきました。 チームメンバーの Yoshimaru46氏 と Miyamizu氏には改めて感謝を。そしてまたぜひ来年一緒に挑戦して予選突破しましょう!!笑
最後になりましたが、isucon 運営の皆様、非常に楽しい大会を提供していただきありがとうございました!!