チーム 😇 (:innocent:) でISUCONの練習ということで,pixiv社内ISUCONを解いた.使用言語は Ruby で,最終得点は94943点.
ネタバレが多く含まれるので続きを読むにします.
リポジトリはこれです.実際の問題と同じくサーバは c4.large,ベンチマーカは c4.xlarge に設定しました.もうインスタンスは削除したので破産しません.
やったこと
- EC2インスタンスを立てた
- ほんとうは ConoHa VPS を借りて ansible 流し込めばいいかなーと思っていたが,うまく適用できなかったので AMI を使った.
- DBスキーマを書き出した
- unicorn にUnixソケットをリッスンさせた
- MySQL への接続にUnixソケットを使った
- 静的ファイルを nginx でキャッシュするようにした
- ここで
/image/:id.:ext
がDBからバイナリを取り出して返していることに気づく.マジで……
- ここで
try_login
で余計なカラムを取らないようにした- このあたりで
id
を取っていないせいでベンチマーカが panic で落ちることに悩まされた.
- このあたりで
make_posts
のN+1問題を (comment 以外) 解決した- nginxの worker_connections を増やしたり,epoll を使うように明示的に設定したりした
- MySQL のチューニングをした
- おおよそ ISUCON4 予選でアプリケーションを変更せずに予選通過ラインを突破するの術 - Hateburo: kazeburo hatenablog の通り.
- メモリが1GBしかないので
innodb_buffer_pool_size = 512M
にした
- そろそろ画像をDBに入れてるのどうにかしたいなーと思い,まず画像をファイルに書き出した
- pixiv-isucon/write_out_images.rb at master · utgwkk/pixiv-isucon · GitHub
- 少しずつ書き出さないとメモリ不足になる
- アップロード時に画像をファイルに保存するようにした
- アップロードされた画像を nginx から配信するようにした
- このあたりで13699点
- スロークエリを見せてもらい,
/
でテーブルをフルスキャンしてることに気づいた - ページごとの枚数制限などを全部
make_posts
に移譲してて,最悪…… - SHA512ハッシュを取るのに外部コマンドを叩いていた(!?)ので Ruby のライブラリを使うようにした
COUNT(*)
が遅いのでインデックスを貼った- これ以外にもいろいろ貼った
- スキーマも保存しておけばよかったですね
- このあたりで Too many open files に悩まされる
- @wass80 に上限を上げてもらった
/
のテーブルフルスキャンしてるクエリを修正した- このあたりで39407点
- アップロードされた画像をgzip圧縮して配信するようにした
- 点数が3倍近くになった(!!!)
まとめ
このようなことを朝10時から18時ぐらいまでやって,最終得点は94943点だった.かなりよくできたと思っている. 画像配信サービスなので gzip 圧縮必要かなと思ってやってみたところ点数がかなり上がったので,最後までしっかり考察して手を動かすべきですね. あとは朝起きるなどの技術が必要.
AMIが公開されているのでシュッとインスタンス立てられて便利ですね.1日ぐらいならそんなにお金もかからないのでよさそう*1.
けっこういろいろ見たけど,こういうときに分かっている人間がチームにいて適切な助言をくれるというのがやっぱり強いですね
— うたがわきき (@utgwkk) 2017年9月10日
ところでこれは私見ですが,ISUCONの練習は手元のマシンでやるよりもAWSとかGCPとか,なんでもいいのでインスタンスを借りてその上でやるのがいいと思う. マシンスペックは保証されてるし,AMIなどのテンプレートが公開されているのでやりやすい. 練習に使うようなインスタンスは1日動かすぐらいではそんなに課金されない*2ので,学生でも手を出しやすいと思う*3.