shiimaxx's blog

最も愛を大切に

ISUCON10予選に参加しました

ISUCON10の予選にnari_exさん、kur_nekoさんと「( (0) / (0)) ☆祝☆」というチームで参加しました。最終スコアは1422でした。
ISUCON7から同じメンバーで参加しているのですが、今年も予選突破できず悔しい。

事前準備

個人練習でISUCON8、ISUCON9の予選問題をGoで解きました。いずれも予選突破ラインのスコアが出るまでチューニングし、その過程で以下のことの練習や確認ができたと思います。

  • レギュレーション、マニュアル、アプリケーション仕様書から問題のポイントをつかむ
  • Goでのオンメモリキャッシュや並行処理の書き方
  • sqlxやgo-redisなどのライブラリの利用方法
  • kataribeやpprofなどの解析ツールの利用方法と解析結果の見方
  • MySQLのロックの挙動について

また、予選の前々日にZoomで打ち合わせをしました。昨年の反省を振り返りつつ、レギュレーションの読み合わせや役割分担を行いました。

当日

それぞれ自宅からリモートで参加しました。Zoomを常時接続しておいて、テキストでの情報共有はSlack、Scrapboxを使いわけて行いました。

序盤

昨年の反省から、まずはサービスの背景やアプリケーションについてしっかり理解してから手を動かそうと話していたので、nari_exさんとわたしでマニュアルを読む、サービスを使ってみる、ということをやって、それぞれScrapboxに情報をまとめていきました。
そのあいだにkur_nekoさんには、サーバの初期セットアップやミドルウェア解析用のログ出力設定などの下回りの整備をやってもらいました。

初回ベンチマークを実行して初期スコアは500ちょっと。
ベンチマーク実行中にtopコマンドの出力を眺めていたらMySQLのCPU使用率が支配的だったので、まずはインデックス追加やクエリの改善・削減をやっていく方針になりました。

今回スコアに直結するエンドポイントは、POST /api/chair/buy/:idPOST /api/estate/req_doc/:id で、そこへの導線になるであろう検索が重要そう、というのがマニュアルを読んだうえでの理解。kataribeでアクセスログ解析を行った結果を見ても検索まわりのURLのリクエスト回数やレスポンスタイムが多かったので、そのあたりを中心に見ていきました。やったことは次のとおり。

  • インデックス追加
  • GET /api/recommended_estate/:id のクエリの修正
    • イスがドアに入るかどうかはイスの短辺だけでチェックすればOK
  • MySQL 8.0化
    • ORDER BY popularity DESCの部分で降順インデックスを使うために採用
    • スコアが下がってしまったのでパラメータチューニングを実施
    • アップデート前よりスコアは下がってしまったが今後の伸びしろに期待してとりあえずそのまま利用継続

中盤

検索APIのクエリでrentdoorHeightdoorWidthなどの条件が範囲検索になっていてインデックスうまく使えていなかったので、それぞれ値に対応したrangeIdを保存するカラムを追加してそれを利用するように変更。

このあたりから/initializeの初期化処理が30秒以内に完了せずベンチマーク実行がFailするようになりました。
インデックス追加、カラム追加とそれに伴う初期データ更新をすべて初期化処理で行っていたので、インデックスやカラム追加後の初期データセットを別テーブル(estate_customizechair_customize)にもっておいて、初期化処理を

CREATE TABLE estate LIKE estate_customize;
INSERT INTO estate SELECT * FROM estate_customize;

でデータをコピーする方式に変更。作業に手間取って1時間くらい消費してしまったのがもったいなかった。

あとはBotからのアクセスが目立ってきたので、NginxでBotからのアクセスに503を返すようにしました。

終盤

この時点での最高スコアは1200ちょっと。予選突破ラインは2000くらいかなと予想していたのですが、残り時間も少なかったので大幅な改修には着手できず。 MySQL5.7→MySQL 8.0でスコアが下がってしまった分をバージョン差し戻しで取り戻せないかな、ということで差し戻してみたのですが効果がなかったのでやめ。
スロークエリログでSELECT COUNT(*)のクエリが相対して多くなっていたので、必要なインデックスをひたすら追加するなどして、最終スコア1422でFinishしました。

まとめ

予選突破ラインのスコアを出すためには施策をもう3、4手打つ必要があったと思っていて、それができなかったのは実力不足だったと思っています。 予選問題のゲーム性の理解やチームの役割分担は例年よりうまく行った感があったので、さらに上積みしつつ来年もチャレンジしたいです。

運営の皆様、今年も楽しい問題をありがとうございました。予選突破された皆さんは本選でも頑張ってください。