開催2年目となるISUCON (Iikanjini Speed Up CONTEST)に参加してきました。
結果は3位。
事前準備
@cadsと@fruweに声をかけ、「Mr. Frank & Co.」という米西独チームを編成。 去年のお題を見ると、簡単なブログサイト。実装はphp, python, perl, ruby, node.jsのいずれか。
- キャッシュ機構入れるんだったら、慣れてるrubyで実装できるようにrailsでスケルトンプロジェクトをgithubに作っておいてみんなで共有。
- VarnishやResque/Sidekiq, Redisの復習をしてコード追加
- 試しに他のrubyバージョンのインストール
- 後はテスト用のec2インスタンスの用意。
お題発表
「NHN48」と「はだいろクローバーZ」のチケット販売システムw。 お、似たようなシステム前作った事あるからいけるかな?セッション対応でもESI使えるからアドバンテージがあるかもと思ってみる。
前半戦
まずは、いつものようにバックアップして戻れるように、gitプロジェクトにも追加。
チームメイト2人にはソースコードを解析をしてもらいつつ、自分は現在の環境の把握とベンチマークを動かすところに集中。どうやら公開されている去年の構成と似た感じでsupervisorによって指定言語のwebアプリが動いている模様。
ひとまず指標となるベースが必要なので、デフォルトで動いているperl版で計ったら大体こんな感じでした。(Scoreが低い方が良い)
Score:533093
Tickets:922
webとdbの負荷が両方高い事を確認。
SQLを見たらCOUNTしてるので、slot分割したcounterテーブルかredisを使えば速くなるよね、と指摘。フロントにキャッシュ入れたいので普段使っているVarnishサポートのlacquer gemがあるので、二人はRailsでの再実装を開始。
ちなみにアクセス分布はこんな感じでした。
perl版のスコアは分かったので、sinatraフレームワークを使ったruby版に変えてベンチマークを取ってみると、
Score:10755528
Tickets:457
性能は約半分。遅いのは分かっていたけど、ジョブワーカーとキャッシュを使えば、対応コードの入ったRailsでもなんとかなるという思いで特に意に介さず。
ただ、unicornが50プロセスもあったので、さすがにこれは多いのでベンチをしつつ、いろいろ調整。 結局スコアが一番高かった10プロセスに落ち着く。ついでにrubyのGCを切ったりしたけど、目立った効果はなし。 まだ再実装中で時間もあり、そういえば速いというrubiniusにしたらどうなんだろうと思い、pumaも入れてみたけどmysql2 gemが動かず断念。
DBのmy.cnfも見たけど、データ量の割には十分なパラメータだったので、commit毎のflushを変えたぐらい。
innodb_flush_log_at_trx_commit = 0
また、いつでも使えるようにと、VarnishとRedisもインストールしておく。
次にデプロイ用のテストができるようにテスト用サーバに環境を用意しつつ、capistrano対応。
後半戦
再実装はブラウザからの見た目上は前半でほぼ出来上がっていて、後はベンチを通るかを確認して最適化を始めるというシナリオでした。 ところが、全然通らずここからハマることに。。
表示エラーなのか遅いからなのか、原因が掴めず四苦八苦。 ベンチマークアプリは未公開なのでエラー内容を運営側に聞きつつ、アプリを修正。
その間、リバースプロクシをapacheからnginxに変えてimages/css/js等のstatic contentを直接配信するようにしたけど、あまり効果がなかったので元に戻す。 アプリ修正の度にベンチを走らせるので、別の作業で最適化の確認をとるのが大変でした。チーム内でcontext switchingの問題が発生!
そうこうしていると時間がどんどん流れ、残り1時間を切ったところでRailsを捨てる決断をする。 せめてキャッシュ入れて最適化しよういう事でVarnishを設定し始める。 そうするとスコアはぐんぐん伸びて行き、上位に食い込む。
Score:180724
さらにESIを使えばもう一段跳ね上がるかもという思いでsinatraにコードを追加してテスト。 しかし、圧倒的に時間が足りず最後の1分半まで粘ったが断念。 最後に再起同時のアプリ起動ができる確認をして終了。
最終スコアは以下の通りでした。
Score:216868
正直ダメかなと思っていたけど、3位という結果に驚きました。 チューニングが実質1時間未満の割にはまずまずかも知れないけど、残念感の方が強かったですね。
反省点
方向性の転換をもっと早く見極めるべきでした。後ちょっと、後ちょっとの思いでずるずる再実装にこだわったのが良くなくて、捨てる勇気を持てたらと。ジョブワーカーやRedis対応の案(とコード)はあったので後半戦直後にやっていたら優勝の可能性はあったかも。。。後の祭りですが。
ともあれ、非常に楽しかったのでまた来年参加してみたいと思います。 運営したNHNの方々、ありがとうございます&お疲れ様でした!
おまけ
帰ってから@netmarkjpさんと平行して#soloconやってました。 直後に公開されたnode.jsで書かれたベンチマークが動かなくてもいろいろ修正したけど、良い勉強になりました。(今は対応版が再アップ済み) chckerがrails版に対して失敗していたような箇所を見つけたので後日検証してみようと思います。