ISUCON12 に Rust で参戦し77位で終了しました

ZARU
Jul 25, 2022

--

今年も参戦しました ISUCON 。大会としては12回目で、参加はこれで4回目。過去全て予選敗退という悔しい思いをして今年を望みましたが、やはり予選敗退。壁を越えることはできなかった。

けど、今までの中で一番手応えがあった大会でもありました。とても楽しかったです。運営の皆さんには感謝しきり。

無謀にも?普段使っていない Rust で今回は参加しました。結果としては 77位、11304 点でした。この記事では、どんな取り組みをしたか備忘録的に残します。

作戦会議

事前に予行練習や作戦会議をしました。方針は以下の通り。

  • 一番大きそうなボトルネックを見つけることに集中する
  • 目の前の明らかに改善できそうな所に、すぐ手を出さない
  • メンバーそれぞれ別のことをやらず、ボトルネックに対し全員で対応
  • サーバ複数台構成は後回しにし、1台でもスコアが伸びる状態を作る
  • とにかく落ち着く

過去の反省から、目の前の甘い餌というか分かりやすいボトルネックを解消しても、スコアは全然伸びず、もっと手前のボトルネックを解消しないと効果がないという経験がありました。

そのため、落ち着いて分析をし大きなボトルネックを見つける方針でした。しかし…

## まさかの SQLite

大会が始まりサーバの中身を確認していくと SQLite っぽいファイルが見つかり「え…?」と思わず声が出ました。当然? SQLite のチューニング経験なんてないです。困った。

代わりに、定番の画像ファイルがデータベースに格納されているネタはなかったです。ここで思ったのは、画像ファイルネタの代わりに SQLite にしたのかな?ということ。つまりサーバ分散化含めて、SQLite をどうにかしないといけないのが初手かという疑問。SQLite を MySQL に移行する大プロジェクト。

何度もその取り組みを頭がよぎったのですが、他チームのスコア推移を見ると2時間程度で1万点近く到達しているチームがちらほらいるのを確認。

さすがにこの時間帯で MySQL 移行が完了している人はそんなに多くはないだろうと予想。MySQL 移行は甘い罠だと感じ、もっと他にボトルネックがあるだろうと後回しにしました。

振り返ると、もっと SQLite に向き合うべきだった…

## ID 生成が大胆

分析を進める中で MySQL の `REPLACE` を使ってユニークな ID 生成をしている箇所が重そうでした。アプリケーションコードを見ると、そもそもこの ID、この生成方法である必要がないと分かったので以下のようにしました。

  • MySQL の ID 生成をやめた
  • ランダムな文字列なら OK なので Rust 側で生成
  • `player_score` テーブルの ID は使われてないので、NULL 状態にした

これが効いてスコアが 2000 から 5000 位まで伸びました。

## N+1 の解消

チームメンバーのペッパーがプレイヤー詳細周りの N+1 を良い感じに除去してくれました。これでスコアが 5000 から 7000 くらいに伸びた。ただし、サーバの負荷状況を見ると明らかに IO 負荷が高い。SQLite の読み書きがボトルネックになってきています。

## SQLite のチューニング

SQLite のチューニング、全然分からないし、何ならスロークエリログとか分析する手法自体を知らないので調べたりしましたが、ぜんぜん良いのが見つからず断念。クエリだけでなにか改善できる方法はないのか?と調べたところ `PRAGMA` でファイル同期モードを切り替えられることを発見。

`INSERT` 系の SQL の前に `PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL;` を追加。これにより高速化される。

結果、7000 から 10000 点の大台に。

## サーバを全て使い切れず終了

この時点で大会終了20分前。実質やれることは少なくタイムアップ。

最低限の MySQL だけ別サーバに分離し、2台の構成になりましたが、残りの1台はまったく付かなかったです。SQLite のままサーバ分散化するアイデアとしては以下を考えましたが、決断するタイミングが遅く手が回りませんでした。

  • 初期テナントは A サーバへロードバランス
  • 新規作成と Admin API は B サーバへロードバランス

こうすることで SQLite ファイルを共有することなくサーバを物理的に分けられそうという感じ。まぁ、着手できなかったんですが。

## さいごに

予選を突破するには 22111 点以上必要だったと言うことで、サーバの分散化ができてたらもっと迫れたのかな?という感じで、悔しいですが一定の成果も出せた実感もあります。なによりハチャメチャに楽しかったです。本当に、毎年イベントの開催・運営をしていただいている関係者の皆さん、ありがとうございます! また来年も期待しています。

--

--

ZARU

株式会社nanabitで働くプログラマです