チーム
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のコネクションをうまく使い回すことが出来なかった・・・。無念