🗂

ISUCON12予選に参加して敗退しました

2022/07/25に公開

ISUCON12 の参加記録です。
大学の知人と mikasi というチームで参加しました。言語は Python です。
メンバーの 1 人が直前にコロナに感染してしまい、2 人での参加でした。
特に役割分担はせず、取り組みました。

commit 履歴は超適当ですが、リポジトリは以下です。

https://github.com/Kazuhiro-Mimaki/isucon12-qualify

やったこと

時系列でやったことを並べます。試したけれどうまく反映されなかった事項も含みます。

Python 実装に切り替え

Python 実装に切り替えました。Python での初期スコアは 1,600 点ほどで Go の初期実装の 1/2 になりました。

alp, スロークエリログの出力設定

準備段階で用意していたものを使用しました。alp のインストールでハマりましたが、メンバーが解決してくれました。

MySQL にインデックスを貼る

EXPLAIN でスキャン対象の rows が少なくなっていることを確認しましたが、スコアはほぼ伸びませんでした。

MySQL サーバーの分割

試みたのですが、なぜか設定が反映されず 30 分経った段階で一旦諦めました。

visit_history の改善

初期実装では、ユーザーがページを訪れるたびに INSERT するという処理になっていました。
しかし、実際に利用されているのはユーザーが最初にページを訪れた際の履歴のみで、初期データ以外のデータは不要でした。
『ユーザーのログをチェックし、既に訪れたユーザーの場合は INSERT しない』という処理に書き換えたのですが、Fail してしまったので元に戻しました。
これが INSERT IGNORE というクエリで実現できることは競技終了後に知りました...

initialize で余計なデータを落とす

先の visit_history に関連して、使っていないのに INSERT されているデータがいくつかあった(Excel のデータとか)ので、それらを利用するデータのみに絞りたいと思ったのですが、具体的な対応方法が分からず何もできませんでした。

competition_ranking_handler の改善

alp で計測した結果、ranking の処理がボトルネックだと分かったので以下のような改善をしました。

  • データ取得後に 2 回 sort していたので、クエリ内で ASC/DESC を指定して、sort 処理を削除
  • N+1 を 2 箇所潰す

少しスコアが伸びました。

SELECT * 改善

SELECT * している箇所を必要なカラムに絞りました。

player_handler の改善

N+1 があったので潰しました。
少しスコアが伸びました。

competition_score_handler のバルクインサート

N 回 INSERT クエリを打っていたのでバルクインサートを試みましたが、うまく実装できずでした。

tenants_billing_handler の改善

スロークエリログで billing の処理がボトルネックになっていると分かったので修正を試みました。
必要データ 10 件に対して全件取得していたので、LIMIT で取得しようとしましたが、この辺りでタイムアップとなりました。

思いつかなかったこと、時間が足りずできなかったこと

他の参加者のブログを読んで色々学びがあったのでログとして残しておきます。

  • キャッシュを入れる
  • DB 統合
  • UUID
  • interpolateParams(Go 実装の場合?)
  • flock の削除

次回に向けて

  • 初期実装を Go -> Python にしただけでスコアが半分になったので、来年参加するなら Go を使いたい
  • よく使うコマンドや設定はシェルやチートシートにまとめておく
  • Sqlite の勉強をしておく...
  • やろうとしたがうまくできなかったことは、どうすればできたかを調査しておく
  • その他、参加者のブログやリポジトリを見て足りない知識を補足する

感想

今回のスコアは、Python での初期実装 1600 前後 -> ベスト 3000 前後という結果でした。
たくさん課題はありますが、『計測からボトルネックを探る』という方針は崩さずに取り組めました。
非常に楽しかったので来年も参加したいです。
ISUCON 運営の皆様ありがとうございました!

Discussion