まーぽんって誰がつけたの?

iOS→Scala→インフラなおじさん技術メモ

SIerだけどISUCON4に参加してみた(チームじゃみお:オンライン予選敗退) #isucon

同期3人組(チームじゃみお)でISUCON4参加しました。

メンバー構成

  • 自分: 普段はiOSアプリ開発の仕事が多く、コール担当もないラッキー人間
  • 同期A: Microsoftに魂を売った男。SharePoint製品の調整を得意とする基盤屋
  • 同期B: 設計、レビュー、顧客調整、深夜のコールををこなすプロ中のプロSE

結果は14,657で17時時点で1日目39/89位。そのあとスコア伸びなかったから多分もうちょい下。

開発合宿でISUCON3をやってみたときは、2,000いかなかったのでどうせダメだろと思ったけど、意外といけてよかった!

ISUCON開始前

8:15に渋谷のエクセルシオールカフェに集まるが、ぼく以外は結局Bash祭りがあーだこーだ話して終了。そんななか、AWSクーポン入力したり、チャットルームにログインしたりとても真面目なぼく。

前半戦

まずは、同期AがLINEカフェのトイレにいったあと、間違えて外に出てしまい中に入れなくなって1人少ない状態でスタート。Amazonさんが無料クーポンをくれたので、豪華にインスタンスを使用。ベンチマーク計測用、各個人用のインスタンスを立ち上げ。 ベンチマーク計測用のインスタンスベンチマーク起動。ruby初期実装でスコア1,200ぐらい。

最初は以下の分担で調査。

  1. DB、Webサーバーなどミドルウェアが何が使われているかを調査
  2. ベンチマークをかけたときのvmstatの値を集計
  3. Webアプリケーションの調査

この中でいちばんコード書いてる仕事にありつけてるのは自分なので、3を担当。3人が触ったことあるのがphpperlpythonだったのでとりあえずrubyperlpythonのアプリケーションの構成を調べた。

rubySinatraPerlPlackPythonはFlaskっていうWebフレームワークでどれも一つのファイル内にルーティングと処理を書けるやつだということ、アプリ本体は1つのファイルにまとまってること、SQLが謎のORMとか使ってないで生のSQLで書いてあるから簡単そうということが分かった。どれも似たような感じだし、どれも使ったことがないフレームワークwだから、とりあえず一番シンプルなファイル構成だった、Pythonを選択!(この選択がのちのち失敗だったことに気づく)

指定通りに、設定ファイルをPythonに切り替えてSupervisorを再起動しても、ベンチマークはfailばっかだし、トップページも表示されなくなってしまった。困った時の再起動ということで、rebootしたらとりあえず動き出したので、ベンチマーク計測。 Pythonにしただけでスコアは1,500ぐらいになった!

後半戦

昼過ぎぐらいからは、3人の調査内容をとりまとめて作戦会議に入る。

まず、vmstatの内容がこれ

f:id:masato47744:20140929220036p:plain

f:id:masato47744:20140929220046p:plain

f:id:masato47744:20140929220055p:plain

f:id:masato47744:20140929221717p:plain

メモリがすかすかでCPUも使い切れてないとのこと。nginxは使ったことないけどそこをチューニングしようということに。そして、nginxのアクセスログを出すように設定を追加して、リクエストと時間を集計したら以下のような結果。

GET / HTTP/1.1    1.478
GET /images/isucon-bank.png HTTP/1.1    3.041
GET /mypage HTTP/1.1    3.161
GET /report HTTP/1.1    18.786
GET /stylesheets/bootflat.min.css HTTP/1.1    3.11
GET /stylesheets/bootstrap.min.css HTTP/1.1    3.05
GET /stylesheets/isucon-bank.css HTTP/1.1    3.066
POST /login HTTP/1.1    49.171
合計 結果    84.863

この結果とソースコードからもloginとreportが改善の余地ありそうだねとなる。

ログインの処理とレポートの処理で、usersテーブルとlogin_logテーブルにselectしてるけどそのインデックスが貼られていないので、users.loginlogin_log.iplogin_log.user_idにインデックスを貼る。

CPUを使い切りたいということで、nginxのworker数と、ベンチマークのworkloadの数を調整。(nginxは初めてだとか言ってたのにvmstatのプロファイリングだけどこれに気づくなんてすごいと思った)my.cnfのチューニングも入れて3人のやつをあわせると、なんと13,793!開発合宿では2,000しか出せなかったから、めっちゃ嬉しくなり、もう終わりでいいんじゃね?となる意識が低い3人組w

この時点で14時ぐらい。

この状態でさらに、vmstatをとってプロファイリングしてnginxのkeepalive_timeoutを短くして、worker_processとベンチマークのworkloadを調整して、14,657が最高点。

アプリケーション側は、reportのところで、for文でselectを投げまくってるところがあったのでそこを修正したかったんだけど、FlaskとPythonデバッグ方法が分からず、修正できず。。スクリプト言語だから直したら速攻反映されると思いきや全く反映されず、rebootしてやっと反映される始末。結局、何もできずに終了><

この辺からは手詰まりになり、デバッグできないからphpに変えてみるかとなっても真っ白な画面になったり、静的ファイルをnginxでキャッシュみたいなことしてパフォーマンスあげられないかなって話になったけど、これも誰も使ったことなかったので勘所が分からず結局ダメ。画像をtiny PNGでサイズを小さくしてみたけど、MD5ベンチマークが見てたためfailになりまくりこれもダメ。nginxにgzipで返すようにしてみたけどこれもfailになりまくりでダメ。

17時ぐらいからはAMIがちゃんと提出できるかrebootを繰り返してbenchを実行したり、焼肉屋を探したりで最終スコアは、14,657で終了。

まとめ

どうせ最下位だよ!とか罵りあっていたので半分ぐらいの順位までいけてよかった!スポーツみたいでアドレナリン出まくりでめっちゃ楽しかったです。運営の皆様お疲れさまでした。 来年は、本戦に出場できるぐらいになるぞ!