bokko bokkoにしてやんよ

A infrastructure and software engineer's blog

isucon#2に参加してきた

南国でぼけ〜としていた時に同僚の@walf443に誘われて二つ返事で参加。チーム名は「くらげとみかん」。

事前にやった作戦会議ではPHP(僕用)でやるかPerl(@walf443用)でやるか前日くらいまで決まらなかったんだけど、 最終的に言語はPerlでアプリケーションの変更は@walf443に任せて 僕がバックエンドのミドルウェアまわりのチューニングやら調整をやることに。

当日やったのはまず、sshの公開鍵と秘伝の.dotfilesを全サーバへコピー。そしてiptablesをオフる。(SELinuxは切ろうと思ったら既に無効になってた)

1
chkconfig iptables off

次にリバースプロキシのサーバをApache(MPMはprefork)からnginxへ切り替え。 しかし、パフォーマンスが大して良くならないどころかむしろ悪くなってるように見えた(断定しない理由は後述)ので結局Apacheに戻す。 このあたりは納得がいかなくて細かいパラメータの変更をかなり試していたんですが、それでかなり時間をロスしてしまいました。 今思うと開始当初は完全にDBがボトルネックだったので、その段階ではリバースプロキシ側ではApacheのMPMをpreforkからworkerに変更するくらいで切り上げて さっさとDBのボトルネック特定やパラメータのチューニング作業に移るべきでした。そっちが一段落してからリバースプロキシ側のチューニングを行えば 違った結果になったかな、と思っています。実際、DBのチューニングがある程度進んだ段階でMPMをworkerに切り替えるとチケットの販売数が倍に上昇しました。 また、ルールを勘違いしていたところがあって、isucon#2ではスコアは小さければ小さいほど良いのですが、 「チューニングしたはずなのになんでスコア下がってるんだ?」と見当違いなことを言ったりして、開始してから2時間近く間違いに気づいてませんでしたorz。

結局上記のことで時間を浪費し過ぎてしまってあとはMySQLのパラメータ(query_cache_size, slow_query_log, etc)をちょこちょこっといじったり、 CSSやJS、画像などの静的ファイルが後段のアプリケーションサーバから配信されていたので、これらをリバースプロキシ側へ移動してそこから返すように変更するくらいしか できませんでした。このあたりは初参加で勝手が分からずあたふたしていたとはいえ、@walf443には申し訳ないことをしたと思っているので、 お詫びに今度なんかおごります。いや、次のisucon3で頑張ります、と言うべきなのか。 あとは最後にログを吐かないようにしたり、デバッグ用の設定を削除してたらあっという間に終了。終了2分前にベンチマークが失敗した時は焦りましたが、なんとか完走できたようです。

まとめ

まず個人的な反省点ですが、開始当初から局所的な細かい最適化に走りすぎました。実際のアプリケーションでもそうですが、 パフォーマンスが極端に悪い原因はある特定のコンポーネントがボトルネックになっているケースが非常に多いので、 まずはそこ(開始当初はDB)を解消することに集中して局所的な最適化は最後の最後に贅肉をそぎ落とすくらいの感覚でやるべきでした。 あるボトルネックを解消すると今度は別のボトルネックが顕在化するといった具合に、 ボトルネックとなるコンポーネントはソフトウェア(あるいはハードウェア)が改善される度にどんどん移り変わっていく傾向があります。

実際の開発や運用と同じように「早すぎる最適化」を避け、その都度一番効果がある対策を実行していくのが一番の近道という至極当たり前な事実を再確認した日でした。