ISUCON12に出て予選敗退した

id:yashigani_wさん, id:wtatsuruさんと、「デジタルトランスフォーメーションズ」というチームでISUCON12に出たけど、振り返ってみたらほぼ初期データを弄って終了してしまったな、という振り返りエントリ。何を振り返ったらええねんと思いながら過ごしていたら時間が経ってしまった。 そういえばチーム名の最後に2022ってつけたいと思ってたのを今思い出した。

当日やったこと

我々のチームでは15分スプリントというのをやっていて、「15分作業 → 5分スプリント会」みたいなサイクルを回していた。これはwtaturuさんが去年のチームでやっていたらしく、今年もやることにした。ということでスプリント会の記録がissueに残っている

https://github.com/tatsuru/isucon12-yosen/issues/3

終盤少しグダッとした場面もあったが、それでも18スプリント回せていたのはよかった

初期データをつくる

手を動かしていた場面はほとんどこれで終わってしまった...

  • 初回のベンチを回した結果を眺めていて、rankingのエンドポイントが遅いので、そこから直そうとなった
  • とはいえどういう作戦にするかをパッと決めることはできなくて、どうやって手を入れるかの材料を集めるのに結構時間がかかってしまった。最終的には以下の作戦でよかろうという話になる。
    • 初期データではplayer_scoreから一つのユーザーが複数のスコアをもっていたので、これを各ユーザー最新の一件のみになるようにデータを作り直す
    • データを入れる時も最新の一件だけになるように
    • player_scoreをひく時は単純にORDER BY scoreでソートするように
  • rankingが遅いのでranking作るところだけ直すか、と話していたところ、結局データを入れるところも直さないと意味がないよねとなり、セットで修正することに
  • 最初は/initializeでこの辺りの処理全部やってしまうつもりで進めていたが、一度ベンチマークを試したら初期化処理に落ちてしまって、作戦を少し変える
    • 振り返ってみるとこの時どういう理由で落ちたかあんまり見てなかったのはよくなかった
  • スコアに関するデータはSQLiteのDBに乗っていて、実体としてはテナントごとに分割されたファイルなので、初期データを手元で作り直してそれをホストに置く作戦にした
  • 各ユーザーの最新のスコアだけ取り出すのは以下のSELECT文で取ってきていた(たぶん合ってると思う)
SELECT * from player_score WHERE competition_id = ? GROUP BY player_id HAVING MAX(row_num);
  • ちなみに初期データを作り直すのもGoで書いた。と言っても元データ取り出してSELECTでフィルタリングして別のDBに書き込むだけなので難しいことはしていない
  • これでplayer_scoreのレコード数が大幅に減った
    • 一番多いところで160万レコードくらいあったのが8万レコードくらいになった
  • 一方でこの辺りでミスが増え始める
    • player_scoreだけ新しいDBに移してしまい、その他のテーブルを移し忘れて/initializeに落ちる
    • 100テナントあることはわかっていたけど、forの条件普通にミスって99テナント分しか移しておらず、やはり/initializeに落ちる
      • 全テーブル移したのになんで落ちるんとか思っていたけど、ちゃんとログ出したら原因判明したし、わかった後はあまりにも恥ずかしくてすまん・・・すまん・・・となっていた
    • 他にもあった気がするけど忘れてしまった。ただ修正→確認のサイクルの時間が長くてだいぶ時間使ってしまった

メモリリークの修正

  • 初期データを作っている横でメモリ使用量が膨らんでパフォーマンスが落ちる問題が起きる
    • 完全に勘だったけど、メモリを使いまくるような処理はcsvの読み込みじゃないのと思ったので、アクセスの傾向を改めて眺めたところ、csvによるスコア登録のリクエスト数が初期実装と比較して増えていることに気づく
    • ここを少し修正してベンチが最後まで通るようになったあたりで概ね時間終了
    • github.com

ふりかえり

  • id:wtatsuruさんも書いていたが、とにかく手が遅い。去年も遅いなと思っていたけど改めて痛感した
  • 与えられた環境で勝負しすぎた。仕事でやったとしてもさっさとSQLiteからMySQLに移行しましょうと言うと思う
    • DB移行は頭には浮かんだものの時間かかりそうだからって後回しにしてしまった
    • 最終的にはどうせやるだろう作業は最初にやるのがよい 
  • ログ出すのも困ったらすぐにやるべきだった
  • 三人で集まって会話しながら作業できたのはよかった
    • ディスプレイを2台置いて、常に片方がペアプロしてるような状況を作れた
    • ホワイトボードで絵を描いて意見を擦り合わせたりがやりやすかった
    • 15分スプリント、5分振り返りで18スプリント回したけど、そうすると会話の時間は90分あることになるが、これは少し長いかもしれないし、そんなことないかもしれない
  • 悔しい結果とはなったけどシンプルに楽しかった
    • 今回は一番ネックになっていそうな部分を順に直していきましょうというのだけ決めていて、その通りに動けたのはよかった

来年また出直します...運営の皆様お疲れ様でした & ありがとうございました。 

メンバーの振り返り

yashigani.hatenablog.com

wtatsuru.hatenadiary.com