ISUCON2026に参加しました
はじめに
今年も @hilotter、@tkuchiki とチーム流れ弾として ISUCON に参加しました。
最終スコアは 77,288 でした。
我らのチームも他のチームと同様にコーディングエージェントの利用をベースに参加しました。
私が Codex を使い、残りのチームメンバーは Claude を使いました。
これには特に大きな理由はなく、普段それぞれが使っている AI Provider を利用した形です。
以下がやったことと、振り返りになります。
やったこと (by Codex)
以下は、競技中の作業記録を参照して、Codex に担当した内容をまとめてもらったものです。
投稿のロックと SQL の往復を減らす
投稿処理を調べると、投稿期間の行を FOR UPDATE でロックしており、同じ地域の別ユーザーの投稿も直列になっていました。
ここを FOR SHARE に変え、同一ユーザーの排他と期間終了時の待ち合わせを維持しながら、投稿同士を並行して処理できるようにしました。
ユーザー取得や保存処理もまとめ、通常の投稿で発行する SQL を BEGIN/COMMIT 込みで 10 回から 5 回に減らしています。
ローカルの PostgreSQL で同時投稿や期間切り替えを競合させ、変更前後の動作を確認しました。
SQL をまとめた際に画像署名鍵の設定が抜け、返した画像 URL が 403 になる不具合も修正しています。
ただし、往復削減後のベンチは PASS したものの、直前の 9,992 点から 8,966 点へ下がり、この試行ではスコア改善を確認できませんでした。
フィードとユーザー検索を DB 側で絞る
フィードは候補を取得してから Go 側で閲覧権限などを判定していたため、条件を SQL 側へ移しました。
通常のフィードでは権限やブロックを判定した後、返す 50 件と次ページの有無を確認する 1 件に絞っています。
ランキングがある友達の友達フィードは同じ LIMIT の付け方にせず、元の並び順やページングを維持しました。
ユーザー検索も DB 側で絞り込むようにしました。
元の Unicode 正規化と case folding を維持するため、Go で生成した検索用の列を登録・更新と同時に保存しています。
約 10 万ユーザーのローカル検証では、ある検索語でアプリへ返す行数が 100,365 行から 29 行になりました。
画像署名のキャッシュとファイル配信
画像 URL の署名は HMAC を 1,000 回繰り返していたので、鍵・画像 ID・有効期限が同じ入力の計算結果をキャッシュしました。
署名方式は変えず、画像の削除や退会などの有効性は毎回 DB で確認しています。
ただし、最初のベンチは 6,886 点から 6,754 点で、ここでもスコア上昇は確認できませんでした。
画像本体は DB からファイルへ移し、認可後に X-Accel-Redirect で nginx から配信する処理を実装しました。
地域間の画像取得や初期化・再起動後の読み取りも検証しています。
途中、nginx の worker 変更で既存の一時ディレクトリへの書き込みが失敗し、export が 502 を返す問題があり、nginx のログから原因を確認して保存先を分けました。
通知のポーリングをまとめる
SSE 接続ごとの DB ポーリングをプロセス内でまとめ、最大 256 接続分を 1 回の SQL で照合するようにしました。
600 接続を 1 巡確認するローカル検証では、従来の 1,200 回から 3 回へ減っています。
接続開始時刻や地域、通知の順序は元の条件を維持しました。
SSE の buffering も無効にし、初回ヘッダーの到達とイベントの到達を分けて検証しました。
access log の応答時間には接続を維持した時間が含まれるため、それだけで通知の遅さを判断しないようにしています。
終盤はポーリング間隔を 500ms から 100ms に変更し、さらに 10ms にする変更も入れましたが、こちらは後に revert しています。
海外の API を DB の近くへ移す
海外のアプリから asia 側の DB への往復を減らすため、友達フィードや通常 API を DB の近くで処理する変更を進めました。
ユーザーの接続先は地域ごとの nginx のままで、運営の回答を確認した転送構成です。
通常 API の転送後は 14,663 点で PASS しましたが、直前の 13,405 点との差には DB の状態なども影響するため、単独の改善効果とは言い切れません。
その後、チームが海外向けの処理先を asia2 へ移した際に、友達フィードだけ以前の asia1 への転送が残っていることを調べました。
nginx が asia2 を選んだ後、アプリが再び asia1 へ転送していました。
goroutine の待機箇所と設定を確認し、nginx が選んだアプリ内でそのまま処理するように修正しています。
やったこと (by 人間)
基本的には ボトルネックになりそうなところを直して と出てきたものを見て、順にやってもらいました。
途中リーダーボードを見ると、このまま積み上げていっても 1 位の点数には届かないと感じました。
そこで 1位はXX点だよ。このままだと多分届かないと思う。何かドラスティックに変更できるところはないの? などと 煽ってました 聞いたりもしました。
そんなことをしながら、昼過ぎの 14 時ぐらいまでメンバーと役割分担して進めていきました。
どうも足掻いても 1 位の点数には届きそうになかったので、@hilotter が予習で試していた「全てを AI にやらせよう作戦」へ舵を切りました。
@hilotter の Claude Code にメインで作業をしてもらいながら、脇で他に改善できそうなところを進めていきました。
最終的に 1 万点ちょいだったスコアが 78,324 点ほどまで上がりました。
最後、人間がデプロイをミスって点数がだいぶ下がりましたが、ギリギリベンチマークが間に合い最終スコア 77,288 点、231 位でフィニッシュしました。
振り返って
分担しての作業はベンチマークかけるところで渋滞してしまった。
コードを書く時間がボトルネックにならないのであれば、ペアプロ/モブプロのように最初から 1 人の Coding Agent を使いながら進めた方が、早かったのではないか。
今回の問題に関しては Codex よりも Claude Code の方が筋のいい修正を提案してたような気がする (根拠はない)。
さいごに
運営の皆さん、今回も面白い問題をありがとうございました!
一緒に参加したチームメンバーにも感謝です🙏。