チューニンガソン02の記録と感想
@la_luna_azulとして「Tuningathon #002」に参加してきました。
http://www.zusaar.com/event/agZ6dXNhYXJyDQsSBUV2ZW50GLmFBgw
結果として10位以内に入れず涙を飲む結果になりましたがスゲー楽しかったです。VOYAGEさん(ECナビさん)、Amazonさん、技評さん、運営のみなさまありがとうございました。参加者のみなさまもおつかれさまでした。今回は敗者となってしまいましたが、おれがやったことと感想を記したいと思います。これを読んだ方がチューニンガソンに興味を持っていただき少しでもイベントの活性剤になると幸いです。次回はさらに盛り上がると良いですね!
競技前
来る2011/10/1(Sat.)、休日はいつも午後まで寝ている僕ですが、11:00頃にはすでに会場に到着しました。んで、ちょっと早めの昼飯を食べながらレギュレーションに目を通す。レギュレーションはまとめると次の通り。
・wikipediaミラー(mediawiki)の読み込み速度を競う
・1並列で100リクエストを捌く(※1)
・URLは無作為抽出1000個からランダムに投げられる
・http_load -rate 1 -fetches 100(※2)
・requests/secの値がスコア
・/var/www/html/mediawiki配下(ドキュメントルート配下)の変更は不可(※3)
・Amazon Linux 2011-02
・AWSのmedium instance×2を使う
・インスタンス2個の使用方法は自由(※4)
・DBの内容の改変は不可(インデックスの張り替えなどはOK)
・主なチューニング対象はApache+PHPとMySQL
・ApacheとMySQLは変えても良い(※5)
・404が出たらペナルティ(※6)
※1:競技中に4並列に変更
※2:競技中にhttp_load -parallel 4 -fetches 100 に変更
※3:競技中にLocalSettings.php(アクセス先のDBなどが定義)のみ修正可能に変更
※4:計測前にターゲットとなる方のインスタンスを運営に伝える。2つをターゲットにしても良い(運営側で計測ターゲットをラウンドロビンする(だったかな?))
※5:条件には書かれていなかったが競技前に説明された
※6:競技開始前に決定
んで、メシを食いながら私用AWSアカウントでAWSのTokyoリージョンにインスタンスを作ってみる。AWSの経験がほとんどないので下見ですね。んで、「へー、カーネル新しいな」とか「お、ext4だ。ext4のオプション調べてみるか」とか「あ、gcc4.4。-march=nativeが使えるな。」「yumリポジトリ結構いろいろ入ってるんだなー」「(ローカルからpingを打ってみて)NWのレイテンシはそんなないな」などと今更ながらAWS下見する。
そんなことをしている内に参加者のみなさまが徐々に集まり始め(mac率高いなー。かくいう俺もMBAでした)、主催者@zakiさんによる競技の説明開始。「デフォルトでは0.7rec/secくらい」「今回はIOが・・・おっと」といったネタバレ(今回の肝はIOじゃなかったけど)ありの競技説明を経ていよいよ競技開始!!!!!!!!!!!!
競技開始
ガラにもなく緊張してました。とりあえず作業効率UPせにゃならんと思ったのでssh-keygenで鍵作成&インスタンスに登録。AWSのログインパスワード長かったしね。
んで、とりあえず片方のインスタンスのhttpdとMySQLを立ち上げてブラウザからアクセスしてみる。「(うっわ!おっそ!スゲー遅い・・・。)」。とりあえずめちゃくちゃ重いことはわかった。重いことはわかったのでボトルネックを探ります。そのためにhttp_loadをもう一方のインスタンスにインスコして計測します。ちなみ競技開始直後はまだアクセス先が明かされていなかったので、http://xxxxxxx/mediawiki/index.php/Japanとかhttp://xxxxxxx/mediawiki/index.php/Linuxとか、404にはならないURLリストを適当に作って計測。計測に使ったツールは定番のtop、vmstat、sar、apacheのserver-status(while true;do sleep 1; curl http://xxxxxx/server-status?auto; done)。iTermの画面を4分割して眺めてました。perfを使ってみたかったですが、競技中は普段慣れているツールが良いですね。
うん、最初の一発目は言われた通り0.8rec/secくらい。たしかにIOにキてた。なのでDBを調査。DBはMySQL5.1でテーブルはinnodb(innodbプラグインではない)。my.cnfは20行くらい(?)の質素なものでパフォーマンスに影響しそうな項目はほとんど入っていなかった。なのでinnodb_buffer_pool_size=1Gとmax_connection=10とinnodb_thread_concurrency=4を適当に入れる。
んでもう一回計測するとiowaitはある程度落ち着きボトルネックは完全にhttpdのCPU負荷になった。MySQLについておこなった最終的な設定はこの程度。query_cacheを効かせたりもしましたがヒット率が全然上がらなかったため最終的にはquery_cacheは無効にしました(とはいえ、今回のルールは参照のみでしたので、ウォームアップとしてできるかぎりクエリキャッシュに乗せるって手もあったかも。まぁ、httpd+phpが肝だったので大きな意味はなかったかもしれませんが)。
これだけで1.0rec/secは普通に超えるようになったかな(計測のログは取っていないのでうる覚えですが)。
CPU使用率との戦い
処理効率を上げるにはhttpd+phpのcpu使用率を下げる必要がありました。これはtopやvmstatを見るだけで明らか。デフォルトで入っているApacheを見ると多くのモジュールが組み込まれていて無駄が多かったので再コンパイルして最適化を図ろうと思いました。
Apacheの最新版ソースを落としてきてexport CFLAGS=”-O2 -march=native”を叩いて、不要なものは極力disableして再コンパイル。さらにMaxClientsを5(競技ルールの並列数4+1としたのは curl http://xxxxxx/server-status?auto を無限ループで叩くため)として再度計測!
うん、phpが動かないのー><
pcreがutf8がサポートがなんとかで・・・ってエラーが出てる。google先生に頼んで必死で調査。yum install pcre-develしてconfigureオプションに—with-pcre=/usrをつけてもう一回インスコ!(たしかこんな感じ!)
動いたー!焦る焦る・・・!
ここまでで1.7(運が良ければ2.0rec/secくらい)まで性能が上がりました。
迷走
さて、こっから(おれにとっての)難敵phpをどうにかしなきゃですが、下手に知らないものと戦うよりも自分の知識でヤった方がいいんじゃないか?という発想に。しかしながらApacheは再コンパイルしてスリム化したうえに、性能に直結するディレクティブは”これしかない”という値にしたのでもうやることがない。静的コンテンツと動的コンテンツが混在しているわけではないので、コンテンツベースで負荷分散を図ることもできない(ってかドキュメントルート配下いじれないしね)。迷走の開始。
・とりあえずmod_expires使ってみる→結果が悪くなる
・Etagsつけてみる→やっぱり結果が悪くなる
・CPU使用率が高いにも関わらず圧縮してみる→1.0rec/secを切るっていうwww
・・・・etc
”phpに処理させたら負け”、”キャッシュを使おう”という発想はあったものの、今回王者の@hamanoさんのようにmod_cacheにつめようという考えが欠如していた点、競技中に開示されたテストデータの2フィールド目がURLの有効/無効を表しているという点に全く気がつかなかったという洞察力の無さがダメダメでした。
そうこうしているうちに運動会のBGMが流れ始め、終焉に向かう。
悪あがき
よくわかっておらず、まったく理解していないがAPCを入れてみる(勉強不足すぎる)。
そしてラストワンプレーで余計なことを・・・。「2インスタンスあるんだしCPUネックだし、Webを2台にすれば早くなるんじゃね?!」といったヤマカンに頼って、この土壇場で今までhttp_load専用だったもう一方のインスタンスでApacheをリコンパイル。
で、最後の計測!
下がってるし!(これは今でも腑に落ちない。なんでだろー??)
失意のまま最後にいらないプロセス(syslogdとかcrondとか)を落とす&chkconfig XXX offなどしてインスタンスを提出。
結果&感想
10位の@ijinさんが2.0rec/secだったのでもうおれは11位以下だなと思った。徐々に上位が発表されて1位の@hamanoさんは3.7rec/sec!1位2位はKlab(と元Klab)の二人!Klabさん強えええ!詳しい順位は技評さんのページにUPされると思います。
個人的に最も良い策だな、と思ったのは2位の@methaneさん。まさに正攻法(phpとapcは最新のものを入れる、nginx、phpのコンパイルオプションはちゃんと選ぶ(たしかこんなことを仰ってたような))。文章にしてみるとあたりまえのことなのですが、その当たり前のことをやるだけでだいぶ性能は改善されるという良い例ですね。
今回は(最近は?)、nginxを使ってる人がけっこういましたね。並列数がそうでもなかったので、僕はApacheで頑張れるんじゃないかと勝手に判断していました(試してないのでなんとも言えませんが)。
とにかく、冒頭でも書きましたがすごく楽しかったです。絶対にまた参加したいです!懇親会では情報交換もできて有意義でした。
また、おそらく恒例と思われるphpディスもあり、ぼくも悔しさのあまりディスらせていただきましたが「phpを知らなかったから・・・」などとは言わずに、普段の仕事においてもどんな相手(システム)にも対応できるように日々スキルを磨かなきゃな、と思いました。懇親会も楽しかったですし良い刺激をもらいました。どうもありがとうございました。
『君には無理だよ』という人の言うことを、聞いてはいけないhttp://becom-net.com/wise/majikku.jonson.shtml
もし、自分でなにかを成し遂げたかったら
出来なかった時に他人のせいにしないで
自分のせいにしなさい
多くの人が、僕にも君にも「無理だよ」と言った
彼らは、君に成功してほしくないんだ
なぜなら、彼らは成功出来なかったから
途中で諦めてしまったから
だから、君にもその夢を諦めてほしいんだ
不幸なひとは、不幸な人を友達にしたいんだ
決して諦めては駄目だ
自分のまわりをエネルギーであふれ
しっかりした考え方を、持っている人でかためなさい
自分のまわりを野心であふれ
プラス思考の人でかためなさい
近くに誰か憧れる人がいたら
その人に、アドバイスを求めなさい
その人に、アドバイスを求めなさい
君の人生を、考えることが出来るのは君だけだ
君の夢がなんであれ、それに向かっていくんだ
何故なら、君は幸せになる為に生まれてきたんだ
何故なら、君は幸せになる為に生まれてきたんだ・・・
人を好きになったり、コミュニケーションしたり、趣味を持ったり、恋人を作ったり、映画やドラマを観たり、音楽を聴いたり、結婚したり、子供を産んだり、親孝行したり、そんななんやかんやが人と同じようにできない言い訳のためにただ仕事している、のかもしれないともおもう。http://twitter.com/#!/treume/status/25531703772
てst
てst