ISUCON12に参加した

昨年に引き続き、ISUCON12 オンライン予選に参加した。最終スコアは 2238 で、698 チーム中 426 位でフィニッシュ。

isucon.net

enokawa.hatenablog.jp

出場の経緯

去年出場して楽しかったので出場した。仕事でも 4 月から Web アプリケーションエンジニアとして Python 書いたりしてたので今のオレのベンチが取りたかった。去年は育児もあって相棒に迷惑をかけたので、1 人の方が気楽だなと思って 1 人で出るつもりだった。

けど、6 月の後半にたまたまハッカー飯@kikulabo さんと話したら「一緒に出ちゃいます?」みたいな流れになって一緒にやることになった。ちなみに @kikulabo さんは元同僚。

@kikulabo さんも Python を多少読み書きできるとのことで、コーディングに関する力量はほぼ同レベルだと思ったので、言語は Python でいくことに決めた。

準備

デプロイスクリプトの作成

昨年の反省も踏まえて、サーバー上で Vim でコードや Config を直接編集するのは、複数台サーバーへの反映が面倒すぎるのでやめたかった。ので事前に ShellScript でデプロイ用のスクリプトを用意した。make deploy-app とかでデプロイできる。予選で使ったけど便利だったので用意しておいてよかった。ちょっと使いづらい部分があって、例えば Download/Upload するファイルパスを ShellScript にコピペする必要がある。YAML とかでコンポーネント(Nginx / MySQL / App / Systemd) ごとにファイルパスを記載するだけでデプロイできるともっと楽かも。

github.com

ISUCON 本を読む

@kikulabo も読んでいて、「このへんは n 章が詳しかったです」みたいに事前にお互いに共通認識を作れたのはよかった。private-isu も通したりして、チューニングの理解を深めた。デプロイスクリプトの作成に時間を掛けすぎて private-isu は全部通せなかったことが反省点。

template repository の作成

前述したデプロイスクリプトだけじゃなくて、開発フローだったり Nginx の conf 例だったり alp のコマンド例などの便利スニペットを用意しておいた。

その他

  • レギュレーション確認
  • 当日やることチェックリスト作成
  • ISUCON11 を 2 人で通した
  • ISUCON11 の予選解説と講評記事を見た
  • ISUCON11 振り返り記事を見た

本番

ログを残していないので記憶が曖昧だけど流れを書いていく。

  • 予選当日マニュアル確認(2 人で)
  • AWS 環境構築 & サーバーセットアップ(オレ)
  • Cfn Stack 作成中にアプリケーションマニュアル読む(2 人)
  • Go のままベンチ(2722)
    • これが最高スコア...
  • デプロイスクリプト微修正 & ソースのダウンロード(オレ)
    • 11:00
  • Python に変更してベンチ(1792)
  • New Relic APM 導入(@kikulabo)
    • 12:30
    • この時点でスコア 1015
  • mysql-slow.log と Nginx の JSON ログフォーマット出力設定 (2 人)
  • APM 見て↓のクエリを改善したほうが良さそうと見当をつける(@kikulabo)
    • SELECT player_id, MIN(created_at) AS min_created_at FROM visit_history WHERE tenant_id = %s AND competition_id = %s GROUP BY player_id
    • EXPLAIN して Using where; Using temporary が出ていることを確認してインデックス貼ろうと決めた
    • tenant_id_idxtenant_id だけ指定してたので competition_id を追加
    • Using where は消えたが Using temporary は出たまま
    • GROUP BY で指定している player_id もインデックスに追加後、rows が 1/10 くらいになって Using temporary も消えた
    • この時点でスコア 1397
  • SQLite がサービスで使われていることを認識(栄野川)
    • 気づくの遅すぎな
    • App x 2, DB x 1 の構成にしたかった
    • SQLiteMySQL 移行を決意
    • 移行めんど。。
    • sqlite3-to-sql あるじゃん!運営ありがと!
      • これが罠だった..
      • 結構手直しが必要そうだぞ
      • webapp/tenant_db/*.db をすべて MySQL にぶちこめばイケる!
      • 全然おわらん。。1d 掛かるんちゃう。。
      • やめた
  • ここからお片付けモード
    • New Relic APM 止める
    • 3 号機の DB みるように設定
    • 2 号機はひましてる
    • syslog 停止
      • うまくできなかったかも
    • mysql-slow.log と Nginx のログの出力停止
    • Redis サービスを停止
    • 1 号機の DB とめる
    • 3 号機の App とめる

良かったこと

  • Docker のままでよかった
    • 最初の段階で無理に systemd に移行しない判断をとれたのはよかった
    • 移行コストが高かった
  • APM Docker にすぐ入れれたのはよかった
    • オレのおかげ
  • EXPLAIN 叩いてクエリの実行計画を確認できたのがよかった
    • ISUCON 本読んでおいてよかった
  • @kikulabo さんの player_id へのインデックス追加が GJ
  • デプロイ楽だった
  • alp 使えたの良かった

反省点

ソフト面

  • サービス再起動時にインデックスがちゃんと適用されているかどうかを確認しておけばよかった
    • ベンチが流れるとき(/initialize)に sql/admin/10_schema.sql が流れると思い込んでいた
    • init.sh をちゃんと読んでいなかった
      • 今見返すと「こりゃインデックスはられないよな。。」となる
    • 何もかも疑ってかかること
  • Go でやりたかったな
    • 個人的に勉強してたので
  • APM に頼りっきりだったのでもう少し自力で改善ポイントを見出す力をつけたい
    • APM いれるとスコア下がるし..
      • しょうがないとは思うけど精神的に少しキツい
  • アプリケーションコード 1 行も更新してない
    • もっともっとコードを読もう/書こう
      • 特にコードを読む力がない
    • デプロイの整備に時間をかけすぎたな
    • template は随時更新していこう

ハード面

  • ディスプレイ 2 枚必要
    • 今回は M1 MacBook Air と 27 inch ディスプレイ 1 枚でやった
      • もう 1 枚 23 inch ディスプレイ余ってたから使おうと思ってたけど単純に HDMI ケーブル挿すだけでは使えない
    • 1 枚は 作業用 & Discord 画面配信用でもう 1 枚は Discord 画面閲覧用
  • スピーカーとマイクほしい
    • AirPods 電池切れるしヘッドセットは疲れる
    • Shokz とか使うといいかもしれない
    • もしくはオフラインでやるか

おわりに

今年も準備不足だった。。たぶん今後も毎年いってると思う。スコアは去年より落ちたけど、コードの理解力だったり DB の理解力は去年よりも上がったと感じる。無力感のほうが大きかったが、充実感もある。

やはり普段から素振りをしないといけない。ので少なくとも 1 ヶ月に 1 回は ISUCON に関する素振りをしたい。ちまちま進めている個人開発プロダクトも Go で書いているので、少し ISUCON を意識して sqlx 使ったりしようかなと思う。(もともと echo は使っている)

とはいえ 1 年に 1 回の開催なのでなかなかモチベーションが上がりづらいなっていうのも本音。いちばんは普段の業務からコツコツと技術力だったり判断力であったりを積み重ねていくのがいいと思っている。

次は 5000 点以上を目指す!やっていくぞ。運営・スポンサーのみなさま、本当にありがとうございました!!!