ISUCON6予選参加記


会社の同僚(J_ogawa,hama_du)とチーム「週５労働撲滅委員会」で参加した。

## 背景

常日頃J_ogawaが週５労働は体に悪いと力説していて、そのためには相応の開発スキルや生産性の高さが必要なので、チーム名を「週５労働撲滅委員会」とした。(命名は私)
業務では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) ](http://okamuuu.hatenablog.com/entry/2016/08/30/213327)
当日はUbuntu 15.04だったようだ。最初にUbuntu 14.04で試したらsystemdの仕様が違っていて起動スクリプトが使えなかった。openjdk-8も非公式だったり。
Ubuntu 16.04では大丈夫だった。

当日と同じような感じで進められるように練習した。
githubのリポジトリで、個人でブランチを作って各自で適宜デプロイいつつ、いいものはmasterにマージする、という感じ。
デプロイはrsyncでローカルディレクトリをコピー。

ベンチでUnicorn直接だといけるけど、Nginxを通すと「リダイレクト先が / でなければなりませんが http～ でしした」というエラーが出てNginx経由のベンチができず。

```bash
#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 予選問題の解説と講評](http://isucon.net/archives/45627361.html)
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?](http://www.eschrade.com/page/why-is-fastcgi-w-nginx-so-much-faster-than-apache-w-mod_php/)
速さに違いが出るのが謎なときはシステムコールの呼び出し回数を測ってみるといいかも、みたいな記事を読んだりした。

一応C++でもいけそうか試した。
[Writing Hello World in FCGI with C++](http://chriswu.me/blog/writing-hello-world-in-fcgi-with-c-plus-plus/)
このページの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で見たらプレーンになっていて、それを直したりしたが、ベンチマークには関係ないので無駄な時間を使ってしまった。午前中の時間の使い方はあまりよくなかった。

キャッシュのバグがつぶせなくて先に進めず、スコアが出なかったが、基本方針は間違っていなかったのかなと思う。くやしいのであとで復習する。
週５労働を撲滅する日は遠い。

とても面白かったので、運営の方々とチームメンバーに感謝!
また来年も出たい!