ISUCON13に参加した

昨年に引き続き、ISUCON13 オンライン予選に参加した。最終スコアは 6,885 で、694 チーム中 353 位でフィニッシュ。

isucon.net

enokawa.hatenablog.jp

github.com

kikuchi-et-al.hatenablog.jp

出場の経緯

一昨年、昨年と出場して楽しかったので出場した。昨年の反省会の時に元同僚の @mmclsntr 誘おうぜって @kikulabo さんと話して、快諾してもらってはじめて 3 人チームで参加することになった。@mmclsntr さんは前職(僕が今所属するアイレット)で Python を書いていたので、とても心強かった。

準備

去年は Go での初回ベンチが最高得点(笑)だったので、最初は Go で行こうという話をしていた。が、みんな学習の時間がとれず Python でいこうという話になった。ちょこちょこ時間を合わせて過去問を問いたりした。オレは家庭の事情であまり参加できず。。あまり準備できないまま本番へ。

0 次予選

今まで培ってきた手動オペレーションの速さを活かして 0 次予選は準優勝だった。(笑いすぎて typo してる)

twitter.com

会場

今回運良くヤフー LODGE で参加することができた。ディスプレイも 1 枚借りれて、ありがたくオレが使わせてもらった。さらにお弁当やコーヒー、懇親会のドリンクやフードもいただけて至れり尽くせりだった。ありがとうございました!

twitter.com

本番

流れを書いていく。(e: enokawa, k: kikulabo, m: mmclsntr)

  • Cfn 流す & サーバーセットアップ (e)
    • その間に当日マニュアルとアプリケーションマニュアル読む (k, m)
  • サーバーセットアップ完了後に初回ベンチ
    • 3,746 (Go)
  • Python に変更してベンチ
  • New Relic 仕込む (k, m)
  • その間に当日マニュアルとアプリケーションマニュアル読む (e)
    • この時点で「アイコン画像配信についての特記事項」見て Nginx でごにょごにょするのは難しそうだなと思った
  • 今回は素振りと少し違った構成だったの手こずった
  • 2,552
  • この時点で 11:23 くらいだったかな
  • users テーブルに name でインデックス貼る (e)
    • 2,541
  • GET /api/user/:username/icon を Nginx で配信してはどうかという話があがった (m)
    • 条件付き GET リクエスト大丈夫かな。。と思いつつ Nginx の location 書く (e)
    • POST /api/iconpublic/icon/{username}.jpg に画像ファイルを配置
    • Nginx で画像ファイルを配信するように修正してベンチ回したが NoImage.jpg を返せず FAIL location ~ ^/api/user/([a-zA-Z0-9]+)/icon$ { alias /home/isucon/webapp/public/icon/$1.jpg; }
  • NoImage はアプリケーションコードで返すように修正 (e, m)
    • 次は条件付き GET リクエストで FAIL
    • この時点で再度マニュアルを読み返し、Nginx ではどうしようもないことに気づく
    • ので Nginx でアイコン配信は行わず、アプリケーション画像配信を行う方針に
  • GET /api/user/:username/iconIf-None-Match: icon_hash を比較して一致していたら 304 を返す (m)
    • 2,729
  • この時点で 15:22
  • app の DB の向き先を 3 号機に変更 (e)
    • 1: app, pdns
    • 2: 暇
    • 3: DB for app and pdns
    • 5,050
  • PowerDNS が参照する DB を 2 号機に変更 (e)
    • 1: app, pdns
    • 2: DB for ddns
    • 3: DB for app
    • 4,109
  • 不要プロセスを停止 (e)
    • 4,382
  • APM外した (k)
    • 6,608
  • DNS レコードの TTL を 600 秒に変更 & 再起動試験 (e)
    • 6,716
  • reaction テーブルの index を追加
    • 6,637
  • livecomment テーブルの index を追加
    • 6,662
  • 終了前に再起動してベンチ
    • 6,885 (最高 & 最終スコア)

良かったこと

  • 前回の最高スコア(2,722) を更新できたのは素直に嬉しい
  • App の DB と PowerDNS の DB を別サーバーに外だしできたのは良かった
  • 諦めずにアイコンのファイル化ができてよかった
    • 途中で条件付き GET リクエストで FAIL し続けて諦めかけていた
      • が改めてマニュアルを読んで「他のAPIで返されるユーザー情報に含まれる icon_hash という値を利用し、~」という文言をみて
      • fill_user_response 関数で icon の SHA256 値参照して返してるのに気づいて底修正したら通ったの嬉しかった
  • 早い段階で再起動試験ができた
  • 初オフラインだったのでコミュニケーションがとても取りやすかった

反省点

  • 一番最初に全テーブルに対してインデックス貼ればよかった
    • ちまちま貼っていたので思い切ってやればもっとスコア伸びたかも
    • 公式の講評みてもそれで 10,000 いってたと書いていたし
  • 条件付き GET リクエストと対応に時間がかかってしまった
    • 結果的に我々の技量で Nginx で配信することは難しかった
    • ちゃんとドキュメント読んでメンバー間で認識を合わせよう
  • 「デプロイします」とか「git pull」してねとかの声掛けが面倒だった
    • ちりつも
  • コード更新してデプロイしてベンチ回して KeyError が出たりしてまたコード直して... の繰り返しが多かった
    • 簡単に動作確認ができたりするといいのかな
    • もしくは Go などの型厳密な言語を利用すればよいのか

おわりに

去年よりスコア上がったけど悔しい!来年は Go でやるぞ!