11月25日(土) 10:00-18:00に開催されたISUCON13の参加記です。
学生チームcktf9として参加し、最終結果は16,255点、総合133/694位、学生13位でした。
この記事は横国公認プログラミングサークルLumosのメンバーによるLumos Advent Calendar 2023のDay 3の記事です!
前日Day 2の記事はmitsuさんの群で理解する ElGamal、明日Day 4の記事は@shion1305のWebフレームワークのパフォーマンステスト手法です。
ISUCONってなに?って人向け
ISUCONとは、Iikanjini(いい感じに) SpeedUp CONtestの略で、お題として与えられたWebアプリケーションを8時間の制限時間内にどれだけチューニング(高速化)するかを競うコンテストです。
毎年異なるWebアプリケーションがお題として与えられ、今回は「ISUPipe」という架空のライブ配信サイトがテーマでした。テーマの世界観については例年出題動画がかなり作り込まれていてわかりやすいので見てみてください。いすこ、推します。
事前準備
ISUCON自体はISUCON11、ISUCON12に続き3回目の参加になります。
これまで友人であるmaa氏との2人チームで出場していましたが、年々増加するタスク量に対してリソース不足に困っていたこともあり、今年は同じく高校の同期であるokoge_kaz氏を加えた3人チームで出場することにしました。
初参加のメンバーもいるため事前準備として本番の2週間ほど前に一度集まり、練習教材としてprivate-isuをやりました。合わせて計測ツール類の選定やデプロイスクリプトの作成、当日の初動タスクの分担なども行いました。
当日
方針
メインの計測ツールとして前回・今年と連続で優勝(!)している@sekaiさん作のpproteinを導入させて頂きました。pprof, fgprof, alp, slpあたりの計測結果を自動で収集・一括可視化できて非常に便利でした。他にもtop, dstatコマンドあたりを併用し、ボトルネックを特定しながらタスクの振り分けを行う予定でした。(まぁ後述の通り本番ではなかなか方針通りには進められませんでしたが)
また、開始直後や終了直前の必須タスクとその分担を決めておく、Discordからコマンド一つで各競技サーバーに一括デプロイできるbotを作っておくなど、前回までの反省点を生かした工夫も行いました。
初動の分担
- ck9
- サーバー起動、ログ収集・集計用サーバーとのトンネリング確立
- Nginx、MySQLなどの各種ログ有効化
- 計測ツール設定
- maa
- デプロイスクリプト配置、必要なファイルをGit管理に
- appへの計測ツールの組み込み
- okoge_kaz
- 当日マニュアル・コードの読み込み
- 改善点の洗い出し
やったこと・スコア推移
時刻 | スコア | やったこと |
---|---|---|
10:00 | – | 競技開始、マニュアル読み込み、上記初動対応 |
11:13 | 3,284 | 初回ベンチ |
11:45 | 3,252 | fillLivestreamResponse N+1解消 |
12:49 | 3,297 | PowerDNS設定(キャッシュのTTLなど) |
13:08 | 3,275 | 不要なカラムを取得しないように変更 |
14:19 | 3,957 | SlowLogを見ながらIndexを貼る |
14:27 | 4,500 | getLivestreamStatisticsHandler N+1解消、さらに追加でIndexを貼る |
15:08 | 5,811 | iconsテーブルにimage_hashカラムを追加し、アイコンのinsert時にハッシュ値計算して格納するように変更 NoImage.jpgのハッシュ値のハードコーディングなど |
15:37 | 8,762 | reserveLivestreamHandler N+1解消 |
16:02 | 9,960 | ここまで全て1台構成で動かしていたのを 1. アプリケーション + PowerDNS(+DB) 2. アプリケーションDB の2台構成に変更 |
16:36 | 11,199 | まだPowerDNS(のDB)の負荷が高かったため、 1. アプリケーション 2. アプリケーションDB 3. PowerDNS(+DB) の3台構成に変更 |
16:58 | 12,207 | moderateHandler N+1解消など |
17:12 | 13,012 | アイコンをDB上に保存するのをやめ、ディスクに保存し配信するように変更 |
17:23 | 16,371 | postLivecommentHandlerの改善、追加でIndexを貼る |
17:37 | 15,927 | 直前でバグを埋め込んで最終failしてしまった前回の反省を踏まえ、これ以上の変更は行わないことに 各種ログの出力オフ、計測ツールの停止など行いベンチマークガチャ開始 |
17:59 | 16,255 | 最終スコア |
反省会・感想など
- タスクの優先度管理
- 計測結果を元にボトルネックを特定し優先して対応する方針を定めたはいいものの、いざコードを目の前にするとどうしても直しやすそうな改善点がたくさん目についてしまい、それらに先に手を付けてしまいがちでした。基本的に現時点でボトルネックになっている箇所以外を改善してもその場ではほとんどスコアが伸びないことを実感しました。(実際競技前半はこまめに改善を加えているにも関わらずほぼスコアが変動せず、後半で計測結果とボトルネックを踏まえた改善を加えるようにしたタイミングから一気にスコアが伸びていることがわかる。)
- 計測結果を元にボトルネックを洗い出してタスク化し、対応できそうなメンバーへのアサインまでする担当を決めておいても良かったかも。少なくともタスク管理はメンバー間でちゃんと共有できる体制を作ったほうが良さそう。
- masterへのマージが遅れた
- デプロイ用のスクリプト内にブランチを指定してデプロイ・ベンチマーク実行できる機能を用意していたのですが、その機能が便利すぎた故に各メンバーが各々のブランチでどんどん最適化を進めてしまったことでmasterへのマージが遅れてしまい、結果として現時点でのボトルネックの特定に支障が出たり改善内容の重複などが発生したりしてしまいました。
- 1つ改善を加えたら動くことだけ確認してすぐにmasterにマージし、できるだけ全員の変更が反映された最新の状態でベンチマークの実行・ボトルネックの特定ができるような運用を行うべきでした。
- DNS水責め攻撃対策の経験不足
- シンプル知識不足
- 公式講評やさくらインターネットさんの記事が参考になりそうなのでこれを機に勉強します。
ISUCONは今回で3回目の参加ですが、テーマが多様で楽しい上、毎回学びがとても多いので次回以降もぜひ参加していきたいと思っています。用意されている初期実装の言語(今回の場合: Go, Node.js, Perl, PHP, Python, Ruby, Rust)も多く気軽に参加しやすいと思うので、気になった方はぜひ参加してみてください。(今回の問題も簡単に環境構築できる形で公開されているのでまずは過去問に取り組んでみるのも良いかもしれません。)
おわり