チーム :thinking_face: *1 として学生枠でISUCON8の本戦に出場しました. 今回のお題は「仮想椅子取引サービス ISUCOIN」でした.
結果は5,981点で14位(ベストスコアは6,324点)でした. 学生の中では5位だったけれどそれ以前に学生のレベルがめちゃくちゃ高かったですね……*2.
やったこと
予選とだいたい同じで,
- id:wass80 がアプリを概観したのちやっていきのある実装をやる
- id:nonylene がインフラまわりの作業をぜんぶやる
- id:utgwkk がSQLを改善したり,すぐできる実装をぱっとやる
という分担になりました.
他のふたりがやったことはそれぞれのブログを読んでもらうとして,ここでは私がやったことを書きます.
https://scrapbox.io/wass80/ISUCON8_%E5%8F%8D%E7%9C%81scrapbox.io
N+1クエリの解消
model/
以下にDBの各tableに対応するモデルファイルが置いてあり,クラスが定義されていました(なんと型アノテーション付き!).
じつはこれは罠で,とくにOrderとTradeにN+1が埋め込まれていました.
N+1のある関数が呼ばれるのは精々数回だったので,丁寧に切り出してJOINに書き換えました.
Fix N+1 on /info by utgwkk · Pull Request #7 · innocent-team/isucon8-final · GitHub
Fix N+1 query on GET /orders by utgwkk · Pull Request #9 · innocent-team/isucon8-final · GitHub
_get_latest_trade()
に LIMIT 1
を付ける
_get_latest_trade()
は文字通り最新のTradeを取ってくる関数なのですが,じつは最新の1件しか使わないのでクエリに LIMIT 1
を付け加えました.
確かこれがいちばん効いて,それまで1000点も出なかったのが突然3000点ぐらいまで上がったと思います.
LIMIT 1 · innocent-team/isucon8-final@9783f73 · GitHub
SettingsをRedisから取ってくる
Settingsは GET /initialize
でのみsetされ,あとはgetしか行われないので,ここをDBから外す作業をしました.
はじめはグローバル変数の dict
に乗せていたのですが,そうするとgunicornで起動したときに /initialize
を受けたプロセスでしか初期化されずFAILしていました.
そのため各サーバにRedisを入れ,そこにSettingsを格納しました.
Do not use database for settings by utgwkk · Pull Request #4 · innocent-team/isucon8-final · GitHub
always get settings from Redis · innocent-team/isucon8-final@24c80be · GitHub
やらなかったこと
インデックスを貼る
今回はインデックスにはとくに手をつけませんでした. 各所に重たいクエリがあるのでまずそちらをどうにかしなければなーと思っていたら競技が終了していました.
ろうそくの改善
ろうそくを出すときにかなり重たそうなクエリが投げられていることは分かっていたのですが,最後までどうにもなりませんでした. MySQL 8.0なのでwindow functionが使えるしなんとかならないか!? と思ったけれどすぐにできるものではなかった…….
SNSシェアを有効にする
終了30分前ぐらいに,SNSシェアしたらどうなるか見てみましょうということで,
res["enable_share"] = True
をやってみたところ当然failしたのですぐに差し戻しました.
懇親会で聞いたところ,appサーバのうちどれか1つだけでSNSシェアを有効にするとか,一定確率で有効にするとかの戦略を取るのが正しかったようです. 巷ではこれをA/Bテストと呼びます.概念は知ってたけどそうする発想が出なかったのでめちゃくちゃ悔しい…….
サーバのリソースにはわりと余裕があったので,少しだけ有効にしてたら10000点は出ただろうなーと思っています.
ユーザのBAN
これも終了30分前ぐらいにエイヤッとやったところ当然failしたのですぐに差し戻しました. そもそもSNSシェアがかなりの割合で有効になってきてから効くようになるとのことだったので,早とちりでしたね…….
感想
テーマとしても面白く,かなり考えられた問題だなーというのが分かりました. 現代のwebサービスはアプリ内部だけ完結せずに外部APIと連携するものが多く,それを踏まえたテーマとなっていたように感じます. 懇親会で他のチームの方や出題者の方々とお話をしたところ目から鱗となる戦略がどんどん出てきて,やはり実力があるなーと思いました.
チームメイトの id:wass80 id:nonylene ,運営の皆様,他チームの皆様,そしていろいろなところでISUCONを支えてくださった皆様ありがとうございました.めちゃくちゃ楽しかったし勉強になりました. 学生のレベルがだんだん上がっており,しかも来年から学生枠がどうなるか不明という話を耳にしてビクビクしていますが来年も出たいです.