ISUCON13にくすサポISUCON部として参加し、9位になりました
くすサポISUCON部、2018年の近鉄パッセ屋上(アイナンダ!リリイベ)での青空コンピューティングから始まり、しばらく弱小だったものの同じメンバーでISUCON11では本戦ボーダー(30位)に約10ランクビハインド、ISUCON12では全体19位で本戦出場、今回は全体9位ということで絶賛成長真っ最中でございます
前回の hogesako.icon によるログ
メンバー紹介
hogesako.icon hogesako : 当日のリーダー的な役割と、主にSQLチューニング担当。アプリも見る sutchi09.icon sutchi09 : 主にインフラのチューニング担当 tondol.icon tondol : おれ。初動のGit化やMakefile導入と、主にアプリのN+1潰す担当 最終的なインスタンス構成
isu1 : nginx + app(golang)
isu2 : PowerDNS + PowerDNSのMySQL(isudns)
ベンチマーカーの向き先はここ, 各サブドメインのAレコードはisu1に向ける
isu3 : appのMySQL(isupipe)
概要
経緯としては上記の通り、同じメンバーでは通算6回目の参加になりますが少しずつ順位を上げられてきており、いよいよ入賞を目指してもいいんじゃないかという成果が出てきているところでございます。今回の最終スコアは147,649ptでしたが、優勝チームは50万近くまで伸ばしていてさすがにバケモンか? という気持ちにもなっております。
メンバーごとの役割はだいたいここ数年で固まってきていますが、使用する言語をGolangに変えたことと(これは言語の良し悪しというよりはコンパイル時にミスに気づきやすいことがISUCONの環境的にプラスに働いている気がする)、また練習会をISUCON本番前にやるようになったのでコンスタントに結果が出せるようになったのではないかという仮説があります。
事前準備は勘を取り戻すために多少過去問で練習したのと、簡単にボトルネック計測やデプロイをするためのMakefileを作っておいたくらいでした。あとは hogesako.icon が毎回適用する秘伝のタレドキュメントを用意していたり。
競技時間中はローカルでのビルドは行わず、基本的にVSCodeのRemote SSHで各インスタンスに繋いで直接ソースコードを編集・ビルドしたり、インスタンス上で稼働しているアプリにブラウザでアクセスして動作確認したりしていました。 タイムライン
スコアはベンチマーク履歴を元にしているので正確だと思われますが、実際のスコア改善とコミットのタイミングにズレがあるので説明は不正確かもしれません。
10:00
競技スタート、マニュアル呼んだり1発目ベンチかけてみたりアプリ触ってみたり
10:09
初期 3,626pt
10:30
10:45
alp-configにマッチングの設定入れてalp結果が見やすくなった
11:05
pt-query-digestの結果を元にCREATE INDEXを実行
今回initializeの処理は各テーブルをtruncateするのみだったので、一度CREATE INDEXを実行すれば永続化された
INDEXの作成対象は livecomments reactions など
6,100pt
12:48
alp結果を元に GET /api/livestream/:id/statictics GET /api/user/:id/statictics のN+1改善
8,246pt
13:02
ミドルウェアの各種パラメータチューニングが入る
10,968pt
13:17
alp結果を元に GET /api/livestream/:id/livecomment POST /api/livestream/:id/livecomment のN+1改善
コメントごとに繰り返し取得していた LivestreamModel は1回だけ取得すればよさそうだったのでそうした
16,914pt
13:44
アイコンを静的ファイルとして配信する改善が入る
21,468pt
ここからお昼食べたりベンチマーカーが止まったりで1h強停滞
15:11
ユーザーアイコンのhashを毎回計算しなくてよくなる改善が入る
32,711pt
15:30
MySQLのリソース消費がボトルネックなのは見えていたので、appのMySQL(isupipe)をisu3に向ける形にする
52,004pt
16:08
POST /api/livestream/:id/moderate の過去の粛清対象コメントを消すSQLが改善
reaction や comment 等の GET/POST で users や themes を取得する処理がN+1になっていたのを改善
この頃になるとalpでも1s/req以上かかっているような極端に重いエンドポイントがなくなってくる
66,161pt
16:20
16:30
appのMySQLに引き続きPowerDNSのMySQL(isudns)をisu2に移動し、最終形に近い構成になった
このときに一緒にslow queryなどもOFFになっていた説がある
72,957pt
16:54
ベンチマーカーの向き先をisu1ではなくisu2にする
これによりisu1のPowerDNSを動かす必要がなくなり、isu1がapp専用になった
リバプロなどなくともisu2のPowerDNSからisu1のipを返せばベンチマーカーはisu1のAPIを呼んでくれる
128,660pt
17:30
GET /api/livestream/:id/search のN+1改善
負荷が上がって再び alp で上位に出現したので改善実施の判断をした
GET /api/tag の結果がオンメモリキャッシュ化される
138,922pt
17:34
各種ログをオフにする
147,413pt <- ほぼ最終に近いスコア
競技終了前
ベンチマーカーが POST /api/livestream/:id/livecomment で 400 を期待しているのに 201 が返ってくると言っており、原因が気になったものの残り時間的に何もできずfinish
go-jsonに切り替えたことによる影響を疑って標準jsonに切り戻したが、特に出力やスコアに変化はなかった
hogesako.icon 曰くDNSがネックになっているとのことだったが、ここもノータッチのままだった
感想
改善すべきところがたくさんあったり、DNSという飛び道具もあったりでやることが尽きず楽しい問題でした。
自分たちのできることは大体やれたなと思う反面、上位チームの話を聞くとまだ自分たちでは思い付けない戦略やISUCONならではの技みたいなものがありそうなので、その辺がまだ伸びしろとしてあるのかなと。singleflightなどを使ったオンメモリキャッシュをもっと早めに活用できるとよいのでしょうね。また、いざとなったら自前でDNSサーバーをすぐ書けるくらいに普段からGolangに慣れ親しんでおく必要があるなと思いました。
今回もISUCON運営・出題関係者の皆様ありがとうございました!
あわよくば来年も同じメンバーで上位狙えたらと思いますが、オフライン本戦でワイワイするのが憧れです……!
https://gyazo.com/0fa99e57f4a9426a4aecadf6af0c798e
https://gyazo.com/723d6440c1b274076f8c9f6d036417b7