🪑

ISUCONで本選進出するために

2022/07/07に公開

ISUCONで本選進出するためにやっておくとよさそうなこと、心構えなどをまとめておきます。

追記

事前講習の資料もおすすめです。この記事よりちゃんとまとまっていて練られています。
ISUCON 事前講習2022 座学 を開催しました(資料と動画と問題あり) : ISUCON公式Blog

この記事の対象読者

  • ISUCONで本選進出を目指す人

本選上位を目指すなら、これに加えて経験とか手の速さとかひらめきとかが必要になると思います。

ISUCONのフェーズ

ISUCON当日の競技時間は大きく分けて3つのフェーズに分けることができると考えています。

初動フェーズ

問題の当日マニュアルを読んだり、インスタンスに入ってチームが作業をするための準備をするフェーズです。
ここで行うことは基本的に、問題によらず変わりません。

僕たちのチームがやる主な動きは以下のようなものがあります。

  • 問題の当日マニュアルを読んで、問題の肝になりそうな部分を探す
  • 計測に必要なツールのインストールや設定の反映
  • インスタンスのコードをリポジトリに追加
  • 悪影響のない秘伝のタレを反映

改善フェーズ

実際に計測→分析→改善のループを回すフェーズです。
自分の腕が試される部分ですね。

僕たちのチームでは各自がローカルでコードを変更して、各自でブランチを指定してデプロイ→ベンチを行い、改善が確認出来たらmainにマージという流れになっています。
ここの部分に関しては、GitHubのPRを利用したり、全員がインスタンスにログインして作業をするなどチームの特色が出る部分だと思います。
ぜひいろんな参加者の参加記を読んで、自分たちのチームに最適な進め方を探してみてください。

後始末フェーズ

競技終了間際に行う、各種ログのオフや再起動試験などを行うフェーズです。
ここも基本的に問題によらずやる必要があります。

準備期間

過去問の解き方

本選進出には過去問をたくさん解くのが一番です。
ですが、今から2週間でということを考えるならば、やみくもに問題数をこなすよりは時間をかけて1つの問題に取り組む方がおすすめです。
時間を決めて取り組んで問題をこなしても計測→分析→改善のループに慣れていない間は、初動フェーズ+インデックスを貼ってみるくらいしか取り組めないことが多いです。それよりはできるだけ改善フェーズに時間をかけて、改善の引き出しを増やした方が本番では役に立ちます。

僕のおすすめはISUCON11予選問題です。
実際の予選環境と同様の環境が https://github.com/isucon/isucon11-qualify/tree/main/provisioning/cf-kakomon でさっと作れる上に「『教科書的な問題でありつつも、解きごたえのある問題』を目指して作問](https://isucon.net/archives/56044867.html#:~:text=「教科書的な問題でありつつも、解きごたえのある問題」を目指して作問)」されているからです。
予選エントリ解説と講評などを見て、もう改善するところがないとなるくらいまでやってみるのが良いです。

時間はあるけど、いきなりISUCON11 予選を解くほどの力はないと感じる人はDSAS開発者の部屋:pixiv private isucon 2016 攻略 (1/5) や 「達人が教える Webパフォーマンスチューニング」の付録についているprivate-isuの攻略実践を参考にcatatsuy/private-isu: 社内ISUCONを解いてみるのがおすすめです。

その他準備期間にやっておくこと

ISUCON予選まであと2週間しかない上に過去問も解かないといけないので、コスパ良く準備をした方がいいです。
以下のものを準備するのをおすすめします。
コンセプトとしては「改善フェーズでコードを書ける時間を最大化する」です。
あらかじめやることがわかっている初動フェーズやデプロイ・分析などをパッとできるようにしておきます。

初動フェーズの手順書

初動フェーズでやることをまとめた手順書を準備します。
ツールのインストールや反映などはAnsibleなどにまとめられるとかっこいいですが、それ自体を準備するのにも時間がかかるのでコマンドのメモとかでも良いと思います。

改善フェーズのイテレーション高速化

コードの変更完了→デプロイ→ベンチマーク→分析のフローができるだけ早く行えるようにします。
凝ったものを作らなくても簡単なシェルスクリプトやMakefileで良いです。
過去問を解いているうちに何度もこのフローを通ることになると思うので、その中で本番でも使えるようにスクリプトを育てる&慣れておくのがおすすめです。

参考までに、僕が使っていたMakefileを置いておきます。
https://github.com/tohutohu/isucon9/blob/master/Makefile

1台構成から複数台構成への変更方法・デプロイ方法

この作業も基本的にはやることになるので手順をまとめて慣れておくのをおすすめします。
特にサーバーごとの /etc 以下のファイルのリポジトリ管理・反映方法とDBのユーザー作成などは詰まりがちなポイントなので事前に決めておきましょう。

後始末フェーズでやること洗い出し

後始末フェーズでやるべきこととそれに必要な時間を見積もっておきます。
どれくらい余裕をもって時間を取るのかは、チームでどれくらいリスクを取るかによります。

当日

ドキュメントを読む

与えられたドキュメントは必ず隅から隅まで読みましょう。
特にソースコードでは実装されていないが、正しく実装することによって大幅な改善が見込める事項は必ずドキュメントにその手掛かりが書かれています。

計測する

ISUCONで戦う上で何よりも大切なのは正しくボトルネックを見つける力だと思います。
どんなにたくさん改善を入れても、その時ボトルネックになっている部分を1つ改善できなければほとんど点数が上がらないからです。
特に最近のISUCONの問題は改善できる点も多く、とても競技の8時間ですべての改善可能な個所を修正しきることはできません。
ですから、なおさらボトルネックを見つけることが大事になるわけです。

そして、ボトルネックを見つけるためには計測が不可欠です。
必ず素早く、正確に計測できるように準備をしておきましょう。

ベンチを回す

計測するにも通じるものがありますが、ベンチは回し得です。
少しでも改善を入れたらベンチを回しましょう。
上位チームは8時間の中で数十回はベンチマークをしていると思います。
(逆説的にそれだけベンチできる改善を入れているというわけでもありますが…)

スコアのブレ

スコアはブレます。
問題にもよりますが、ベンチを回すたびに±10%くらいスコアがブレても驚かないようにしましょう。
確実に改善になるものを入れても、逆に少し得点が下がるといったことが発生する場合もあります。
原因としてはスコアのブレだったり、ボトルネックが別の場所だったりするので自信があるならできるだけ残しておくと後々のボトルネックを先につぶすことができるかもしれません。

改善の分類

秘伝のたれによって解決するものを除けばISUCONで行うような改善は以下のものに分けられます。
後は計測してどこがボトルネックなのかを特定し、それに合わせた改善を入れればおのずと得点は上がっていきます。

スロークエリログからわかるもの

  • DBのインデックスが正しくない
    • → 正しくインデックスを貼る

ソースコードからわかるもの

  • N+1になっているクエリがある
    • → N+1を解決する
  • 無駄な処理が実行されている(外部コマンドの呼び出しなど)
    • → アプリ内やクエリで解決できないか考える

プロファイラからわかるもの

  • 特定の処理の実行回数が多い
    • → 可能ならキャッシュする、難しければ負荷が減るようにする
  • メモリの確保・開放が頻繁
    • → オブジェクトプール(sync.Poolなど)を利用する

topやdstatからわかるもの

  • CPU使用率がMAXで張り付いている
    • → 構成変更を検討する

当日マニュアル・レギュレーションからわかるもの

  • キャッシュできるものがキャッシュされていない
  • 遅延させられるものが遅延していない
  • まとめられるものがまとめられていない

↑3つはちゃんとドキュメントを読むことと過去問のドキュメント+講評などを読むことが対策になると思います。

まとめ

いかがでしたか?
めちゃくちゃ雑に書いてしまったので見返して、修正追記するかもしれません。

Discussion