会社の同僚(J_ogawa,hama_du)とチーム「週5労働撲滅委員会」で参加した。
背景
常日頃J_ogawaが週5労働は体に悪いと力説していて、そのためには相応の開発スキルや生産性の高さが必要なので、チーム名を「週5労働撲滅委員会」とした。(命名は私)
業務ではRuby/RailsなのでRubyで参加することに。
練習1 pixivの社内ISUCON
各自で予習する。普段はRailsを使っていて、Sinatraは未経験なのでまずそこから。
NginxやMySQLの設定、ローカル環境で動かす、indexを貼るなど、基本的なところのみやってみた。
Slackを使い始める。
練習2 ISUCON4予選
実践的な練習ということで、部屋を借りて4時間ほどやる。なお部屋はSpaceeで探した。(安くて良かったけど、レビューを読むとWifiが使えない部屋も多いようなので、確認したほうがよい)
各自で環境構築や、重そうなところの共有など。
rack-lineprofで解析、Redisでキャッシュするなど、ISUCONでよくあるアプローチをやってみた。
refererがないときはNginxで静的ページを返せば爆速になりそうだが、そこまで至らず。
練習3 ISUCON5予選
同じ部屋が予約できなかったので、会社でやることに。
ちょうどこちらの記事があがっていて、Azureだしこれに挑戦。
isucon5 予選の復習を Azure 上でやってみる(1)
当日はUbuntu 15.04だったようだ。最初にUbuntu 14.04で試したらsystemdの仕様が違っていて起動スクリプトが使えなかった。openjdk-8も非公式だったり。
Ubuntu 16.04では大丈夫だった。
当日と同じような感じで進められるように練習した。
githubのリポジトリで、個人でブランチを作って各自で適宜デプロイいつつ、いいものはmasterにマージする、という感じ。
デプロイはrsyncでローカルディレクトリをコピー。
ベンチでUnicorn直接だといけるけど、Nginxを通すと「リダイレクト先が / でなければなりませんが http~ でしした」というエラーが出てNginx経由のベンチができず。
#TARGET=IP_ADDRESS:80
TARGET=IP_ADDRESS:8080
jq '.[0]' < ../webapp/script/testsets/testsets.json | gradle run -Pargs="net.isucon.isucon5q.bench.scenario.Isucon5Qualification $TARGET"
のように切り替えていたのだけど、あとでわかったが、Nginx経由かつポート番号を指定するとだめだったらしい。
userを丸ごとキャッシュした。最初(クラスのメンバ変数ではなく)インスタンスのメンバ変数に入れていたせいで、アクセス毎に全ユーザを読み込んでいて実は遅くなってたとか、いろいろなバグをエンジョイする。
帰宅後、こちらを読んで一通り試す。
ISUCON5 予選問題の解説と講評
rack-lineprof、ログの取り方、Nginxの設定、kataribeの使い方などを復習した。
1000件取得してから友達かどうかでフィルタして10件取得するのと、relationをjoinして10件取ってくるのだと結果が違わないか? とか、push型(ユーザー毎に友達の日記ID用のテーブルを用意して、自分が日記を書いたときにそこに配信するやりかた)のときに、友達を追加したら過去のぶんにも配信しないといけないのでは、などコーナーケースを考えてみたり。(今回のベンチマーカーはそこまでチェックしていないっぽい)
予選突破ラインは13898点だったらしいが、解説記事の手法なども取り入れたけどAzure Basic A3 (4 コア、7 GB メモリ) だと7000点くらいしかいかなかった。やりかたがまずいのか、GCEの性能が高いのか?
その他
UnicornをPassenger(Raptor)に切り替えたら速くなるのか、調べたり試したりしたが、全体に与える影響は軽微なようなので、やらなくて良さそうだった。
Why is FastCGI /w Nginx so much faster than Apache /w mod_php?
速さに違いが出るのが謎なときはシステムコールの呼び出し回数を測ってみるといいかも、みたいな記事を読んだりした。
一応C++でもいけそうか試した。
Writing Hello World in FCGI with C++
このページのFCGIのサンプルはとてもわかりやすく、簡単に試せた。ただ今回はRubyでチーム戦をするというのと、MySQLやRedisにアクセスするコードまでは書かなかったので、使わなかった。
当日
10時
初期設定はPerlでスコアは3283。Rubyに切り替えたら0になった。
Nginxでcss,img,js,favicon.icoを配信するようにした。
11時
isutarをisudaにマージしてdeployする。がホームディレクトリを全部消してしまいインスタンスを作り直す。ちょっと焦る。
クア・アイナの配達を頼んで気持ちを盛り上げる。
12時
keyword_lengthをカラム化したり、インデックスを貼ったりしてスコアが4000くらいを記録。
htmlifyが一番重そうなので、キャッシュするのと、処理の中身を軽くする方法を模索する。
13時
キーワード一覧をRedisにキャッシュするが、いくつかのページにキーワードが含まれていないと言われ、FAIL
14時
htmlifyの結果をキャッシュする。キーワードの更新(追加または削除)を記録するテーブルを用意して、キャッシュの作成時間よりもあとに更新されたキーワードがdescriptionに含まれていたときだけhtmlを再生成するようにした。スコアが10000を超える。
16時
キーワードの一覧をviewで一回だけ取得するようにした。スコアが30000を超える。
17時
ハッシュ化したキーワードをキャッシュしてみたが、FAIL
17:59
masterブランチに戻してqueueに投入して終了。18時ちょうどに見えなくなり、最終スコアは不明。33000くらい?
感想
事前に練習したおかげで、共同作業はおおむねうまくいったと思う。
VMのインスタンスを作り直す際、運営の方のレスが早くてとても助かった。(ストレージがacceptedから進まないので質問したが、結局待つだけでよかった。まっさらから作ると15分くらい必要だった)
CSSのcontent-typeがtext/plainでChromeで見たらプレーンになっていて、それを直したりしたが、ベンチマークには関係ないので無駄な時間を使ってしまった。午前中の時間の使い方はあまりよくなかった。
キャッシュのバグがつぶせなくて先に進めず、スコアが出なかったが、基本方針は間違っていなかったのかなと思う。くやしいのであとで復習する。
週5労働を撲滅する日は遠い。
とても面白かったので、運営の方々とチームメンバーに感謝!
また来年も出たい!