おそらくはそれさえも平凡な日々

ISUCON14参戦記 (カラアゲネイティブ 14,987点)

今年もISUCONに参戦した。今年も無事に開催され、素晴らしい出題と運営で良かった。ありがとうございました。

いつものカラアゲネイティブなメンツで出ようと思っていたが、 @toricls さんが出場できなかったため、私が技術顧問を務めているMOSH社CTOの村井さんを無理やり誘ってチームを組んだ。と言うことで、今年のカラアゲネイティブは、 @motemen, @RyosukeIketeru, @songmu の3名。言語はGo。リポジトリはこちら。

https://github.com/motemen/isucon14

序盤の作戦会議

  • 競技開始後、いつものようにmotemenがインフラ周りを設定している間に、村井さんと僕との二人でマニュアルとレギュレーションを読み合わせる。motemenも耳で参加
    • ここはなんだかんだで1時間くらいかかるが大事な工程
    • シミュレーター含めて細部まで良くできててビビった
      • 細かくアプリを触らないと分からないボトルネックがあるという運営からのメッセージなのか?とか思ったけど、結果的にはそういうわけではなさそうだった
  • 今回はアプリケーション部分の改善と仕様の調整がスコアに響いてくる点が新機軸で良かった
  • 取り合えずレギュレーション読んで以下の3点が攻略ポイントだとあたりをつける
    1. 決済周りの冪等キーヘッダ対応
      • これは単純にやれば良いだけという話っぽい (実際そうだった)
    2. 通知の改善
      • 最終的にマニュアルに書いてある通りSSE化まで辿り着けるのが理想だが、そこに行く前に潰すべきボトルネックが色々ありそう
    3. マッチング改善
      • ここが本丸っぽい
    4. 最後まで下二つの改善が課題になるので、そういう意味では分かりやすい問題だったと言えるかも

前半戦

  • まずは肩慣らしに簡単そうな冪等キーヘッダの対応 #10
    • 初期実装のワークアラウンドクソコードに対するFIXMEコメントがリアリティあって良かった
  • マッチング処理のエンドポイントが定期的に叩かれてアクセスログを汚すのもイヤだったのでgroutine化 #12
    • マッチングエンドポイントを叩くプロセスは止める
    • 念のため設定ファイルのINTERVALを3600にも設定した
    • if hostname != "ip-192-168-0-11" { と言うクソコードによりマッチングロジックが1台でしか動かないようにもした
    • これらによって後のマッチングロジック改善がやりやすくする狙い
  • interpolateParams=true #17
  • goccy/go-json 投入 #18
    • いつもお世話になります!
  • 3台負荷分散 #19
    • アプリケーションをisu01, isu02で動かしDBをisu03に移動
      • マッチングロジックはisu01でしか動かないように
    • しかし今や僕はISUCONでしかNginx.confを触らなくなってしまった

この頃合いに、motemenと村井さんがpt-query-digestを見ながらインデックスの追加だったり、テーブル構造の変更などをやってくれていた。

だいたい、前段のやるべきことは終え、後半戦は想定通り本命のマッチングと通知の改善かな、と言うところに至った。ただ、この時点で15時近くなっていた。てこずって時間をかけすぎたのでこのあたりもう少しスムーズにやりたかった。何はともあれ、通知周りの改善は他の二人に任せ、僕はマッチングの改善に取り組むことにした。

後半戦

  • 当初のマッチングロジックがあまりにもひどかったので修正
  • とりあえず、chairs.is_occupied というカラムを追加し、配車中かどうか判別できるように
    • 初期状態で配車中の椅子がなかったのは助かった
  • しかしこのステータス更新で苦しんだ
    • マッチング時に is_occupied = true にするのは簡単だったが、解除するタイミングがよく分からずてこずった
      • ライド完了時にフラグを戻してしまうと、椅子が完了通知を受けとる前にマッチングが始まってしまいエラーになる
      • 完了通知のところでフラグを戻そうとすると、マッチング待ちが長くなりすぎてエラーになる
    • ここは根本究明できず、ライド完了時に、非同期で200msec遅らせてgoroutine内でフラグを戻すという酷いコードを書いて通した
    • これで少しスコアは上がった
  • ここで時間切れ
    • このロジックでは単に空いてる椅子が適当に選ばれるだけになっていて元のロジックと大差ない
    • ちゃんと近傍を割り当てる最適化に取り組みたかったのだが…

と言うことで、終了間際に回したベンチが通って、14,987点でフィニッシュ。順位は多分103位。

反省

  • 良問で運営やポータルも快適で、コードも色々書けたので楽しかった
  • 誘った村井さんも楽しんでくれたようで良かった
  • Goに不慣れな村井さんをもう少しフォローできれば良かった
  • motemenが苦労しているときにも、ペアプロするなりすればもう少し早くバグに気付けたかも
  • このあたりはmotemenがインフラ構築担当であることもあり、アプリの理解度が少し落ちると言う点も影響があったかも知れない
  • インフラ構築担当がコードも書く体制なら、インフラ構築後にマニュアル熟読担当が構築担当に問題概要をレクチャーする時間があっても良いのかも
  • 何なら来年はインフラ構築担当を切り替えても良いのではないか
    • カラアゲネイティブチームは、結成初年度は僕がインフラ構築担当だったが翌年からずっとmotemenが担当しているし役割が固定化している
    • 今年の構築はめっちゃ早くてトラブルもなくて熟練を感じた
  • いつものメンバーのスキルセットは近いので、それぞれの役割分担が固定化している今、それぞれがやっていることを棚卸しして他の人ができるようにする価値はありそう
  • マニュアル読みに時間はかけるのは必要だけど、その後の初速をもっと速くしたい
  • ISUCON用ツールを自作するのとかもやっても良いかもと思い始めた
    • これまで、僕が結成時に作ったものの注ぎ足し、注ぎ足しされた秘伝のMakefileを一枚持ち込むのみで戦ってきたが限界がある
      • このMakefileはマジで便利
    • アイデアとしてはスコアの記録とか、pt-query-digestやperformance schema, alp辺りの集計をいい感じにしてくれる君とか
  • 一緒に組んでて、僕よりmotemenの方がISUCONに勝ちたい気持ちが強い感じがするので、来年はもう少しそこに協力したいかな
  • 何にせよ来年も開催されることを期待しています
    • ありがとうございました
created at
last modified at

2024-12-17T01:11:15+0900

comments powered by Disqus