大西ブログ

All your blog are belong to us

ISUCON3予選に参加しました

ISUCON3の予選に参加してみました。
結果、一般枠10位で、無事予選突破、本戦に進めることになりました。わいわい。
ISUCON1は気付いたら終わってて、2は出ようと思ってたけどスケジュールの都合がつかず、今回が初参加になります。
チームメンバーは id:motemen, id:wtatsuru ダブルチーフ&ダブルタツルのダブルダブルチームです。チーム名は Third Party Cookies。はてなブログサードパーティクッキー受け入れを推奨しています。


撮影 : hitode909

インフラはwtatsuruに任せ、アプリ周りの改修をmotemenと分担。分担と言っても思いついたことを思いついたままにやっていただけなので、もう少し戦略とか考えていくべきだった。事前準備も何もしてなかった。redbull買ったくらい。
以下、自分が何をしたかを適当に書きます。他のメンバーの方が頑張ってた。

markdown

外部プロセス呼び出してるので明らかにネックになってる。最初は ALTER TABLE して formatted_content カラムを追加、markdownを展開した結果を保存、起動スクリプトでも初期データをformatしておくという実装にした。
が、起動スクリプトが重くなると、ベンチマークが気軽にできないなーと思い直して、最終的には外部プロセスで実行しないように変更するのと、展開結果をmemcachedにキャッシュするだけに留めた。

クエリ改善

ORDER BY created_at DESC, id DESC は完全に無駄。id は primary key なので 単に id DESC に置き換えた。
recent の深いページの OFFSET の大きいクエリが重いので、id のみを引き、WHERE IN で * を引き直すことに。最初のクエリは id しか引かないことでインデックスで完結するのでクエリは増えるがトータルで速くなる。

セッション

users テーブルは通常のページでは id と username カラムしか表示されないし、それらの値は不変(変わるインターフェースが無いから)。だから users テーブルを引く必要は無い。session に id と username を格納するように書き換えた。
最後の方で、ベンチで FAIL しなければ何をしても良い戦略に切り替えて、session にストレージも使用しないようにして、cookie のvalueに単に id=1,name=onishi という文字列を格納するようにした(ひどい)。
実際の運用でも、cookieのvalueにデータを格納する事は暗号化すればアリだと思ってる。
セッションでユーザーを復元しても、それは「ようこそ○○さん」の表示にしか使われない、といったことはウェブサービスでままある。表示に使うusernameはcookieに入れておいて、本当に必要になった時だけ DB を引く、といった戦略は実際のサービスでも有用だと思う。

プロファイリング

拙作、Devel::KYTProf は常時有効にしている。無駄なクエリが発行されてないかとかに注意しながら開発できす。これで stylesheets="/" とかは一瞬で気づけた。

carton exec plackup -s Starman -p 5000 -E prod -MDevel::KYTProf --workers 10 app.psgi

ちゃんとしたプロファイリングのためには Devel::NYTProf は必須ですね。

NYTPROF="sigexit=int" carton exec plackup -s Starman -p 5000 -E prod -MDevel::NYTProf --workers 10 app.psgi

みたいな感じでDevel::NYTProfでプロファイリング。PlackアプリのNYTProfでのプロファイリングは tokuhiromさんが昨日書いてたエントリに詳しい。勉強になります。Devel::NYTProf で Starlet/Starman (Plack) でうごくウェブアプリケーションのプロファイリングをおこなう方法まとめ - blog.64p.org

その他

ほかにもこまごまやったけど僕がやった中ではあんまり価値のある情報は無いです。チームメンバーのエントリ参照

感想

準備不足だったなー。ってのが言い訳になっちゃうのでよくない。正直、10位は悔しい結果だった。アクセスログの解析とか、ベンチマークとか、デプロイ方法とか、事前に決めておいたり準備しておけることたくさんあった。
社内IRCに専用のチャンネル作る、社内GitHub Enterpriseにリポジトリ作る、っていうのは良かった。デプロイは手動 rsync でやってたけどよくなかった。
お昼ごはん食べる暇もなく8時間があっというまだった。頭酷使してすごく疲れたけど充実してて楽しかった。企画・運営のみなさんに感謝です。本戦頑張ります!