どうもコンニチワ。
去る2011.7.9に開催されたチューニング大会 tuningathon に参加してきました。 結果は2位。惜しかった!すごくすごく楽しかったです。
よくよく考えたらうちの会社のクライアント企業の方々もいらっしゃっていたりして、こりゃ負けられないぞ、と気づいたのは結果発表が半分すくらい済んでからでした。 まぁあまり細かいことは気にせずみんな参加したらいいと思うよ!俺が許す!
主催のゼロスタートさんと技評さん、会場提供していただいたECナビさん、サーバ提供していただいたAmazonさんありがとうございました!
さて、今回は結果が出てほっとしたわけですが、具体的に何をやったのかメモっておきますのでご参考まで。 問題解決のアプローチを晒す意味で、やったことを順番に書いてみます。 ちなみに環境はMacBookAirです。会場のほとんどの人がMacでしたね。
- まずtop,vmstat,計測画面を起動
チューニングの基本は計測・測定なので、それがスムーズにできる環境をつくりました。 操作するウィンドウとは別に1つウィンドウを起動。 screenで3分割して、top,vmstat,測定シェルを常に出して、いつでも見られるようにしておきました。
- とりあえず測る
phpなのにapc入ってないってのはあまりにもなので、apcインストールして、あと net.ipv4.tcp_tw_reuse
をOnにしてまず計測してみました。
この時点で20並列1000回で70秒弱だったでしょうか(うろおぼえ)。
twitterのTLでも話題になっていましたが、この時点でCPUバウンド確定だったのでターゲットはapache/phpに絞りました。 ・・・とはいえどうしてもやってみたかったので、mysql(/var/lib/mysql)をtmpfsにしてみました。 だがしかし!、やっぱり何も変わりませんでした(あたりまえ)。
skip-innodbも設定しましたが効果なし。 innodbに変えた人もいたみたいですが、今回のテスト条件ではinsertとselectが重複することはあまりなさそうな気がしたのでMyISAMのままにしました(実はそうでもないのかもしれませんが)。 時間ないし。
もしtmpfsで改善するようであれば、mysqlを多段にして前段はtmpfs、後段(replication slave)でデータ維持しようと思ってました。 DB処理のキューイングですね。 もしそうなったら、起動スクリプト改変して、起動時にデータ投入する予定でした。 今回はその前でサチってたので関係なかったけどね。 ちなみに、計測の度にdeleteしてoptimize tableしたほうがいいな、と気づいたのはだいぶ後半になってからのことでした。。。
- 試行錯誤1: apacheいじってみる
vmstatで見るとusr8割・sys2割、topで見るとhttpdがほぼ全て、という状況だったので、apacheのプロセス数を20に絞ってみました。 んで計測。結果変わらず。残念っ!
- 試行錯誤2: phpいじってみる
どうにもこうにもphpを速くするしかないって状況になったので、もうこれはphpがんばるしかないか、ってことでphpリコンパイル(最適化)とfastcgi化を決定。 fastcgi使ったことなかったけど、まぁこれしかあるまいということで手をつけました。 phpのfastcgiは怪しいので使わない、という話もあったけど、postdataを確認して中身がstaticだったので、今回のケースなら誤キャッシュしても結果は変にならないってことを確認して進めました。 (それでも怖かったので計測の度にテーブル内のエントリ数はcountしてた)
apacheもうだめぽな気分になっていたのでapache + nginx + php-fpmの3段構成に決定。
nginx + php-fpmが事例多そうだったのと、nginxは経験あって設定がわかりやすいのを知っていたのでさくっと決定。
nginxはインストール手順が手元にあったので一瞬で完了。
でもphpは一苦労でした。。。最適化オプション -O3
でコンパイルして計測したら、10秒くらいでテスト完了するように。
あまりにも速い!のでテーブルのエントリ数えたら・・・増えてない orz
さんざんデバッグしたあげく、mysqlサポートつけ忘れてwordpressが死亡していたと気づいたのが終了1時間前くらいだった気がする。
ここでおやつとして持参したredbullを飲んで気合いれてリコンパイル。300円以内なのでレギュレーション的にも問題なし! php-fpmの使うの初めてだったのでドキドキしたけど、設定詰まらなくてよかった。。。 今回のポイントはCPUを使い切ることだったので、php-fpmの並列数を2(CPUコア数と同じ)に絞ってリトライ。 結果は50秒切るくらい。
この時点で@methaneさんが43秒台出していたのをTLで見ていたのでちょっと絶望的な気分に。。。
- 悪あがき
この時点でCPU使用率としてphp-fpm x2が80〜90%、mysqlが 15%くらいでした。 ちょっと打ち止め感があったので他の思いつくことをやってみることに。 この時点で残り15〜30分なのでたいしたことはできませんでした。 ざっと試したことは・・・
- apacheのworkerとeventどちらが速いか試す→どっちでも変わらない
- apacheのログ出力抑止→たいして変わらない(一応出力止めた)
悪あがきしてみたものの、あまりタイムかわらず終了。 この状態であれば、mysqlをtuneしたら少しは効いたかも。 と、いうわけで
懇親会でもいろんな方とお話させていただきました。 ありがとうございました。 んで改めて感じた大事なことはコレ。
- 計測してターゲットを絞ること
- 超定番はひと通りやるにしても、それ以上のことは勘でやってもうまくいきません
- ボトルネックの解消に全力を注ぐこと
- ゴールドラット博士のザ・ゴールの話も出ましたが、ボトルネックの解消がミッションです
- 今回はボトルネック移動しなかったので、ボトルネック移動する環境だともっと幅が出て面白いとおもう次第
- あきらめたらそこで試合終了
- 途中で環境が壊れて泣きたい時もあるけれど、あきらめなければきっといいことがあります
- ある意味で手段を選ばないことは大事。自分の得意なパターンに持ち込めなそうならさくっと切り替えましょう。チートはバレないように
- 壊れても戻せるような準備はしておいたほうがいいよ。バックアップとか
おまけ
こんなぼくから技術を盗みたいエンジニアの人はハートビーツの中途採用に応募するといいと思うよ!
ハートビーツのようなMSPは、エンジニア業というよりはサービス業なので、よりスリリングに楽しめます ;)
See also
- #isucon チーム「ウー馬場ーイー222」でISUCON13本選に参加し30位になりました
- 「SRE≠インフラなんだけどもう誤解されちゃってるから、DevOps新実装としてSite Production Engineeringはいかがでしょう?」でJAWS DAYS 2022に登壇しました #jawsdays #jawsug
- #isucon チーム「シン・ウー馬場ーイー2」でISUCON12本選に進出し12位になりました
- #isucon チーム「シン・ウー馬場ーイー2」でISUCON12予選に参加し2位で予選突破しました
- 「非ITの事業会社にSREと言わずにSREを持ち込んだ」SRE NEXT 2022で登壇しました #srenext