ISUCON5予選で散ってきた

2015-09-28
ISUCON5

チーム

yokohamanorth というチームで出場。

役割分担は下記の通り

  • データベース、インフラ全般 @bati11
  • 環境構築、ミドルウェア設定 @trtraki
  • アプリケーション改修 @hanhan1978 (オレ)

やったこと

自分はアプリケーション改修担当だったので、とにかくアプリの改修に集中しようと努力しました。

開始直後にPHPの初期実装が不安定でベンチが回らないということが判明し、軽く動揺したものの、
アプリの内容が複雑だったので、PHPを捨ててRubyで行くことに。

他のPHPerに対しては、下記のようなツイートで牽制。(深い意味はない・・・)

#isucon PHPerがPHP以外に何を選択するというのかね?

— Ryo Tomidokoro (@hanhan1978) 2015, 9月 26

PHPで行く気満々だったので、ミドルウェア系の準備の大半が無駄になりましたが、そのままガリガリと修正。 インデックスページがボトルネックであることは、kataribeの結果から明らかだったので、クエリの数と複雑性を減らすという方針で修正。

  • entriesのN+1クエリをjoinへ変更
  • commentsのN+1クエリをjoinへ変更
  • commentsにカラムを追加、entryのuser_idを突っ込んで、temporary tableを使うクエリを削除
  • entriesにタイトルカラムを追加、bodyをselectしているクエリを修正し、titleだけ取るようにした。
  • インデックッスページのview内でN+1クエリをやっている箇所を追加したentryのuser_idを使うように修正。

これらの修正と、mysqlへの4つのインデックス追加に加えて、unicornのワーカーを4に増やしたことで、最高で7500くらいのscoreまでは到達しました。 さらにusersテーブルのredis化を試みてる最中に時間切れとなりました。

反省

  • PHPで準備しすぎたため、PHPが不安定という情報で動揺があった。
  • 動揺を引きづったため、各担当者が担当外の物事に首を突っ込むことが多かった。
  • 烏合の衆と化して、全体を俯瞰してみる人がいなくなってしまい、チューニングが場当たり的になってしまった。

とにかく悔しさで胸が一杯です。振り返ってみて、Rubyを選択したのは悪くなかったですが、その後がよくなかったです。 ISUCON6が開催されるかどうか、まだ分かりませんが、また何倍もレベルアップしてきますので、是非開催してほしいです! ありがとう!そしてさようならISUCON5!! 下記は、当日やったことを時系列でまとめたものです。 予選落ちチームですが、参考になればどうぞ。

当日のタイムライン

  • 8:00 作業場所に集合

  • 8:00 ~ AM9:30 暖気運転として、isucon4を使った仮想isuconを行った。 この段階で、kataribeが直近でアップデートされていて、ちょっと使い方が変わっていることに気づく。 => 本番中に遭遇してたらテンパるところだったので、危なかった・・・

  • 9:30 開始が11:00に延期。と同時にnodejsの実装が無くなった旨の連絡が来る。 m9(^Д^)プギャーしてた。

  • 11:00 各メンバーは、初期割当のタスクを粛々とこなす。 アプリの説明書きを読んでいくと・・・、PHP実装が不安定という記述を発見。 PHPでやる気満々だったため、愕然とし、nodejsをm9(^Д^)プギャーしたことを謝罪する。

  • 11:45 データベース等のチェック終了 アプリのURL洗い出しと、画面遷移の作成完了 isucon4予選とくらべてもURLの数が多く、アプリケーションがまあまあ複雑であることを確認。 この時点で、不安定なPHPの選択肢を排除し、Rubyを選択した。

  • 12:00 kataribeの最初の解析結果を確認。 「/」が突出して遅いこと、isucon4で金鉱脈だったcssのリクエストが1回しかないことを確認。 事前練習において、「大変そうに見えてもボトルネックから目を逸らしてはイケナイ!!」という合言葉をグループで連呼していたので、 「/」の改善に取り組む。

  • 12:00 - 13:30 最初に作成したインスタンスから、スナップショットを作って、各自が作業するという流れだったが、 何故か、スナップショットから作ったインスタンスで、mysqlが起動しない。 初期状態のままのはずのアプリがうまく動作せずベンチ出来ない。 => PHPが使えないことで、若干動揺があったため、インフラ周りのゴタゴタにチーム全員で取り組むという愚策を行ってしまった。 最終的には、運営から共有された初期イメージからそれぞれがインスタンスを作り直して、作業するという方向で落ち着いたが、2時間弱ロスする。

  • 13:30 - 14:00 アプリケーションが遅すぎて、ベンチがコケることに気づく。 インデックスを3つほど貼って、ベンチが安定して成功するようになる。 scoreは200くらい

  • 14:00 - 15:00 footprintテーブルにindex貼ったら、score2000くらい unicornのプロセスを1->4に増やしたら、5000点くらい。 この時点で2位。とても幸せだった。 「/」のN+1クエリを2箇所撲滅 scoreは5500くらい。

  • 15:00 - 16:00 commentsテーブルに対するクエリがボトルネックっぽかったので、 カラム追加して、JOINをなくすことに。 select * でtext型の取得をやめる 上記2つの修正が完了して、score 6000くらい。

  • 17:00 enttirsテーブルにtitle型でカラムを追加して、bodyを取得するのをやめる方針。 対応はすぐ終わったけど、alter文とデータ移行に30分くらい 17時後半くらいからfootprintsのgroup byをなくす作業にとりかかる

  • 18:00 上記の修正を提出用インスタンスに適用。 ビューのN+1問題を解決して、7000超え。

  • 19:00 footprintsのgroup by 問題は解決出来ず断念。 userのredis化は、15分程度でとりあえず動くようには出来たが、むしろscoreが下がった。 => 予想はしてたが、コネクションプールされたmysqlで、メモリに乗ってる情報の検索は、十分高速 => ruby力が低くて、redisのコネクションをうまく使い回すことが出来なかった・・・。無念