ISUCON11予選に参戦しました。
はじめに
3人メンバーのチームでISUCON11予選に参加しました。
決勝にいけるような好成績ではなかったのですが、それなりに健闘できたのでブログを書いてみることにしました。
はじめに投稿したのが予選から1日後です。公式の解説や他の方のブログを読んでチューニング部分に関して反省とかを更新していくと思われます。
時間の流れ (だいたい)
私視点での自チームの様子を記載しました。コミット見直したり覚えている範囲で記載してみた。まとめて思ったのは実装スピードが遅いなと。
- 10:00~ マニュアル読む。アプリを触る。
- 10:30~ デプロイスクリプト、分析・監視系ツールを導入する。
- 11:30~ 分析結果を基にマニュアルをもう一度読んだりして方針をそれっぽく議論する。
- 12:00~ お昼を食べながらモクモクとチューニングをはじめてみる。
- 14:00~ 「テーブルへのインデックス貼り」や「ユーザーのインメモリ化」などで16,000点(?)くらいになる。
- 14:30~ 「GET /api/trend のN+1クエリ対応」ができ、25,000点(?)くらいになる。
- 16:00~ 「画像のConditional GET 対応」をするも、もろもろ知識が足りていないせいでfailし続けてしまいスコアを伸ばせず。
- 16:30~ 「MySQLを2台目サーバへ移す」で34,000点くらいになる。
- 17:00~ 「POST conditionの非同期化」をするもスコアにそれほど影響せず、35,000点くらい。
- 17:15~ 継続してトライしていた「isuテーブルのインメモリ化」でもスコアが伸びず。
- 18:00~ 私「は?コンディションのグラフ?それは一体美味しいのでしょうか?(丁寧)」
- 18:30~ さらにスコア伸ばすこと叶わずそのまま終了。お疲れ様でした!
使った分析・監視系ツール
- top
- dstat
- kataribe
- pt-query-digest
- go tool pprof (1回しか見れていない)
ベンチを走らせるときはtopを見る癖を付けるようにしました。dstatでもちょいちょい見ていた。本当はNetdataを導入してイケてる画面で監視しようとしていたのですが準備が間に合わず。
kataribeはISUCONには欠かせない相棒に。alpを使う人の方が多いかもですが使い勝手はほとんど変わらないと思います。
スローログはpt-query-digest様、これも欠かせない。
担当したチューニング部分の中で、自分のためにブログに残す箇所
GET /api/trend のN+1クエリ対応
N+1クエリ対応において、SQLの割と基本的な知識が足りておらずバグが取り除けずハマっていました。
「SQLでグループごとにある最大値の行を取得する」をする必要があったのですが、以下の記事での"失敗例"のように集約していないカラムが適当に引っ張られてしまう状態でした。記事のように同テーブルでJOINして行を保証する必要があることに気づくのに時間をかけてしまいました。普通に修行が足りてません。
SQLでグループごとにある最大値の行を取得する - Qiita
メモとして残しますが結果的に以下のSQLになりました。複雑そうですがEXPLAINで見てINDEXは効いてました。
select i.id, i.jia_isu_uuid, i.character, ic.condition, ic.timestamp from isu i INNER JOIN (select icA.jia_isu_uuid, icA.timestamp, icA.condition from isu_condition icA INNER JOIN (select jia_isu_uuid, max(timestamp) as timestamp from isu_condition group by jia_isu_uuid ) icB ON icA.jia_isu_uuid = icB.jia_isu_uuid AND icA.timestamp = icB.timestamp ) ic ON i.jia_isu_uuid = ic.jia_isu_uuid;
MySQLを2台目サーバで動かす対応
ちゃんと効果ありました。アプリとMySQLが1台目サーバのCPUを食い合っていたのでそりゃそう。MySQLサーバをアプリケーションサーバから剥がすチューニングはどの過去問でも大体同じように効果が出ると思われます。アプリケーションのCPU負荷が見えてきたらひとまずやってしまうと良いと思っています。
画像のConditional GET 対応
ベンチマークが「Conditional GET のサポート」をしているとマニュアルに記載があり、対応を試みたのですがFailしてしまいうまくいかず自分の基礎的な実力不足を思い知りました。
マニュアルに貼られていた以下のRFCのドキュメントをこの際、上から読んで勉強しようと思います。
POST conditionの非同期化 対応
今回のお題のISUCONDITIONにて、ISU(椅子)からやってくるデータ登録部分をgoroutineでサクッと非同期化しこれはコスパ良く点が上がるのではと思ったのですがあまり上がらず。やり方が良くなかったっぽい。
おわりに
運営の皆様、お疲れ様でした & 楽しく学びになる時間をありがとうございましたm( )m