ISUCON6 のオンライン予選に参加しました

2016/09/17(土)と2016/09/18(日) に行われた ISUCON6 のオンライン予選の2日目に参加しました。
ただまぁ、結果は惨敗でした。。。
でも MAX で一応 1 万点までいけたので嬉しかったです。

1
2
Score 9431
Best 11145

とはいえ、途中トップのチームが 40 万点とか出してて心がくじけました。。。
つらつらとやったことと良かったこと、次回に向けてをまとめていきます。

今回は会社のインフラエンジニアの人を誘って参加しました。
私は主にアプリの方を担当しました。

やったこと

最初に、相方がデプロイなどのインフラ周りを整えて、私はソースコードリーディングをして、DBやアプリケーションの構成を把握しました。
(この時点で、何かツール、 rack-mini-profiler とかを入れてボトルネックを洗い出せばよかったと反省しています…)

アプリの内容は、問題作成担当のはてな社らしく、記事一覧があって、記事にスターがつけられるというものでした。
アプリの構成は、 isuda と isutar の 2 つで、メインが isuda で、スターを付けるところの処理が isutar というものでした。

デプロイ後に一度ベンチマークを取ってみたのですが、初期スコアは0点でした…。
それから2時間くらいはひたすら インデックスを貼れる場所を探したり、 N+1 問題がないかを探していました。
結局はそんなに SQL には問題がなさそうということで、過去問でその辺りに重点を置いて勉強した私は…。って感じでした(^_^;)
幅広い知識は身につけておけっていう教訓ですね。

あとは、 isutar はスターを管理するためだけだったので統合してしまったほうが早いのでは?と思い、統合しようと頑張ったのですが、
Illegal mix of collations というエラーが出ていて解決できずでした。。。
そこに 1 時間くらい時間を使ってしまったのですが、本当にそれで早くなるのかも怪しかったので諦めました。
ただ、後で友達と話したときには、そもそも DB を使わないで Redis とかでやってしまったほうが良かったのでは?という話もして、
あーたしかになるほど。って思いました。

結局、やれたのは

  1. SELECT 文で SELECT(*) になっているところを必要なものだけにした
  2. entries の後の each で perttern の生成をするのを最初に一度だけやってメモリにのせた
  3. 記事数を取ってくるのに、 select count(*) from entry を、 Ruby の size を使うようにした

くらいでした。
多分一番効果があったのは 2 番目のやつくらいで、今思うと私がやったことはほとんど意味がなかった気がします。。。
3 番目のやつなんかはむしろ遅くなってるんじゃないかっていう指摘もいただきました。
もっと精進します。

良かったこと

主に準備とか環境周りですね

  • あらかじめキーの追加など必要な設定はレシピに書いて、それを cook すれば始められる状態になっていた(相方がやっていただきました)
  • 上記とは別にリポジトリを用意して、アプリを github で管理した。
    • 一応 pull request を作ったのも、今見返せるようになっているので良かったと思っています。
  • それぞれのアカウントでリソースを立てて、私のを検証用環境にできた
    • 一時、本番側の設定が戻せなくなったときも、検証用環境をみてすぐに復元できたのはでかかったなと思います(Azure は起動に時間がかかりますし)
  • 2 人で参加して、インフラとアプリで明確にやることを分けた
    • 完全に分けたわけではないのですが、作業がかぶるとかそういったことは少なかったのは良かったかなと思います

次回に向けて

  • rack-mini-profiler を使えるようにする
  • スロークエリログは出せるようにする
    • 過去問解いてて出せなくてハマっていたので解決したいです
  • nginx, unicorn 周りのログを読めるようになる
  • Redis をいつでも使えるようにしておく

は身につけておきたいです。

最後にメモ

最後に、ページネーションの処理のところで知らなかったのがあるのでこれはメモです。

1
2
3
4
SELECT * FROM entry
ORDER BY updated_at DESC
LIMIT #{per_page}
OFFSET #{per_page * (page - 1)}

という SQL があったのですが、 OFFSET を使うと遅いらしいですね。
http://d.hatena.ne.jp/pospome/20130827/1377592854

LIMIT + OFFSET はテーブルフルスキャンらしく、データ量が多いと処理に時間がかかるとのこと。
今回はデータ量がそんなに多くなかったのでボトルネックにはなってませんでしたが、
良い学びになりました (*´ω`*)

謝辞

そんなこんなで初の ISUCON は残念な結果にはなりましたが、次回までにもっと勉強してリベンジしたいと思います!!
参加登録まで 1 週間前とかで誘ったにも関わらず快く参加してくれた @tjinjin さん、ありがとうございました。
事前準備やら段取りなどもやっていただいて頭があがらないです。
また、問題を作成されたはてな社、ピクシブ社にも感謝しています。良い問題でした、ありがとうございました m(_ _ )m