ISUCON 13 参加レポ

ISUCON とは

ISUCON とは「良い感じにスピードアップコンテスト」を略したイベント名で、8 時間以内にお題となる Web サービスの高速化を図るチューニング協議大会。2023 年で第 13 回を迎えた。
いくつかレギュレーションはあるものの、基本的にどんな高速化の手段を用いても構わない。
競技用ベンチマーカを実行した時の点数によって順位が決まる。優勝賞金は 100 万円。
1~3 人でチームを結成して協議にエントリーできる。

https://isucon.net

役割分担

だるぷ( https://github.com/mitixx )と 2 人チームで出場した。

相方の記事はこちら → https://mitixx-blog.netlify.app/blog/isucon13/

相方に nginx 周りのチューニング担当、私は初期状態のバックアップ・測定ツールの導入・DB 周りのチューニング・アプリケーション周りのチューニングを行った。

チューニングする Web サービスの実装言語は、Go, Ruby, Nodejs, Python. Rust, PHP, Perl, Java などから選択できる。
PHP を選択したいところだが、Go の方が実行速度が速い関係上、PHP に切り替えるだけでベンチマーカの点数が下がるため、Go のままチューニングする。

問題傾向(ざっくり)

ライブストリーミングサービスをチューニングする。
同時視聴できた人爺=ベンチマーカの点数になる。(初期は 3000 点ほどなので約 3000 人。)
ミドルウェアは例年通り nginx と MySQL。
ISUCON では、その回特有のクセのつよい構成・それに伴うボトルネックがあったりするが、今回は、名前解決を PowerDNS で行っている・画像をバイナリ形式で DB に保存している、などが見受けられた。

できたこと

初期状態のバックアップ。
これは、チューニングで問題が発生したときにロールバックできるようにしておくため。
GitHub に Web サービスのソースファイル、各種ミドルウェアの設定ファイルのバックアップを取るべく、リポジトリを作成して push しておく。
DB 作成のクエリファイルはファイルサイズが大きくなりがちなため、ローカルでコピーを取っておく。

測定ツールの導入。
alp、pt-query-digest、Netdata を導入した。
alp とは、nginx のアクセスログを解析して、実行に時間がかかっているリクエストを見やすくするツールである。
pt-query-digest とは、MySQL のスローログを解析して、遅いクエリを見やすくするツールである。
Netdata とは、システムリソースをダッシュボードからグラフィカルに表示・監視できるツールである。

MySQL チューニング。
メモリの割り当てとか不要なファイルを生成させないとか。

スロークエリを pt-query-digest で解析してインデックスを貼る。
解析 →EXPLAIN→ キーが使われていなければインデックスぺたぺた。

プリペアードステートメントをアプリケーション側で処理する。(動的プレースホルダにする。)
これで、DB 側でクエリを組み立てることがなくなるため、DB のリソース削減につながる。

+ conf.InterpolateParams = true

Go 側で Echo の DEBUG ログが吐き出されている状態になっていたので停止させる。

- e.Logger.SetLevel(echolog.DEBUG)
- e.Use(middleware.Logger())
+ // e.Logger.SetLevel(echolog.DEBUG)
+ // e.Use(middleware.Logger())

不要なサービスの停止。 snapd、ufw、rsyslog、apparmor などなど。

できなかったこと

アプリケーション周りのチューニング全般。

相方がやってくれたこと

bot アクセスをはじく。nginx を複数台構成にする。

結果

700 チームくらいが参加の中、最終順位は 316 位で点数は 9028 点。
ベンチマーカの初期スコアから約+6000 点くらい。

感想

目標として「初期状態から+3000 点」を掲げていたので目標は達成したが、相方に任せっきりなところが多く、手を付けられたところが少ないため、個人的には悔しい。

初参加の感想としては、手をつけられる部分が多すぎてとにかく時間がない。
各種ファイルのバックアップで 1 時間ほどかかってしまっていたので、GitHub へのバックアップはある程度自動化する、妥協するなどして時間を削減した方が良いなと感じた。
また、細部ばかりに注目せず、全体を見通して、改修できそうなところから手を付ける必要があるなと感じた。残り時間わずかで map 使ってキャッシュするだけで早くなりそうな箇所を見つけたときは頭抱えた。

あと、Go をビルドした成果物を直接 service に実行してもらうべく、service ファイルを修正したあたりでベンチマーカが Fail して 50 分くらい時間を無駄にしたのがとにかく悔しいしモヤモヤする。
エラーが出ているわけでもなく、とりあえずロールバックしまくったら復帰できたので原因不明。
来年は気を付けたい。

pt-query-digest を見ながらボトルネックになっている箇所にインデックスを漏れなく貼れたのと、PREPARE が解析結果に出てきていることからプリペアードステートメントをアプリケーション側で処理するようにチューニングできたのは良かった。

ただ、出場する上で確実に力を付けられたこと、対策・競技中めちゃくちゃ楽しかったのも事実なので、悔しさをバネに来年もがんばりたい。

来年の目標

今回、N+1 改善、キャッシュの導入などまで手が回らなかったので、初動対応の時間を削減する、Go・sqlx への理解を深めて短時間で多用できるようにして、手を回せるようにする。
このあたりの「どんな出題でも絶対に行うようなチューニング」を確実に実施できるようにして、アプリ側のロジックの改善に取り組める時間を確保する。

相方に nginx 周りのチューニングを丸投げしてしまったので、nginx のチューニングを勉強をする。

ISUCON13 では 25000 点以上で 100 位以内に入れたようなので、最終スコア 25000 点を目標にしたい。