ISUCON2016予選に出るので知見を漁った

ref: YAPC::Asia 2015 「ISUCONの勝ち方」 / Masahiro Nagano
https://youtu.be/vl1mYTq1ZYI

## これまでのISUCON

* ISUCON 1 2011/08
    * 出題: livedoor (NHNになる前）
        * 問題: ブログのコメント欄
* ISUCON 2 2012/11
    * 出題: NHN Japan
        * 問題: チケット販売サイト
* ISUCON 3 2013/10（予選）2013/11（本選）
    * 出題: 面白法人カヤック
        * 予選: nopaste
        * 本選: 画像投稿＋TL
* ISUCON 4 2014/09（予選）2014/11（本選）
    * 出題: クックパッド
        * 予選: パスワードリスト攻撃
        * 本選: 動画広告
* ISUCON 5 2015/09（予選）2015/10（本選）
    * 出題: トレジャーデータ
        * 予選: SNS? （N+1クエリ問題）
        * 本選: 間違ったマイクロサービス
            * Yahoo! PipesやIFTTTみたいなやつ

## チーム編成

* 1人じゃ結構無理
* 効率よく作業を分担し、お互いの作業をチェックし、ミスを減らす
* コミュニケーションコストを減らすため普段から一緒に業務を行っているメンバーでチームを作った方が有利

## コミュニケーション

* 「会話」を重視
* リモートならチャットかビデオチャット

## 時間配分

* 意外と短い
* 最初の1時間は慌てる時間じゃない
    * 課題の理解
    * プロファイリングとチューニングの方向性を決めることだけに使う
* 最後の30分は再起動テストに残す

## 事前準備

* Private Git Repository
    * ~~人に見えてもいいならPublicでもいい~~ **ダメです**（matsuuさん ブコメ恐縮です）
* Wiki
    * メンバーのSSH公開鍵
    * 秘伝のタレ
        * コピペで使えるように
        * my.cnfとか nginxとか
* Slack
* 技術選択についての簡単な打ち合わせ
* 過去問を解く
    * http://d.hatena.ne.jp/tmatsuu/20150815/1439643715
    * EC2やGCPで試してもいい

## チューニングの進め方

### 課題の理解

* スコアの算出方法、失格条件を調べる
    * 幾つまでのエラーは大丈夫みたいなこともある
    * http://www.slideshare.net/tagomoris/isucon2014
* とりあえずベンチマークを動かす

### プロファイリング

* アクセスログ解析
    * ツール
        * [analyze_apache_logs](https://github.com/tagomoris/Apache-Log-Parser) ([使い方](http://www.slideshare.net/kazeburo/isucon-yapcasia-tokyo-2015))
        * [kataribe](https://github.com/matsuu/kataribe/)
    * 全部を見ながらどこをチューニングするか相談する
        * 一番アクセスが多いのは画像だったりするかも
* MySQLのスロークエリ解析
    * クエリの実行回数と頻度の両方を見る
    * ツール
        * [pt-query-digest](https://www.percona.com/doc/percona-toolkit/2.2/pt-query-digest.html) ([使い方](http://www.slideshare.net/kazeburo/isucon-yapcasia-tokyo-2015))
        * つけっぱだとベンチマークで重くなるので気をつける（service mysqld restart）
* アプリケーションのプロファイリング
    * 各プログラミング言語のツールを使う
    * ツール例
        * strace
        * tcpdump
* サーバの負荷の確認
    * top - 全体の負荷
    * iftop - ネットワーク
        * 動画広告問題の時はネットワークがボトルネックだった
    * iotop
    * dstat

### サーバ構成の把握

* Client -> Reverse Proxy -> App Server (-> RDBMS, -> Cache, KVS)
* どのようなサーバ、ミドルウェアが動作しているか
* サーバ、ミドルウェアの設定
* 過去にはtypoや罠も

### チューニングの方向性を決める

* チューニングすべき対象
    * 大量のデータの参照
    * 多サーバとの通信
        * 特にラウンドトリップのコストが大きい新規の通信開始
    * 大量のプロセス／スレッドの調節
        * コンテキストスイッチングを減らす
* 目指すアプリケーション
    * 何もしないアプリケーション
        * 参照を減らす／しない
        * 通信を減らす／しない
        * プロセス・スレッドを減らす／しない

## チューニングのヒント

### Webサーバの選択

* nginxはプロセス、H2Oはスレッド
    * スレッドの方がコンテキストスイッチのコストが低い
    * スレッド間の情報の共有がしやすい
    * とはいえ、やってみないと分からない部分は多い

### アプリケーションのチューニング

* わかりやすい重い処理
    * 外部プロセスの起動
        * markdownのフォーマット
    * HTMLテンプレート処理
    * テキスト／画像変換処理
    * RDBMS／Cacheとの接続
        * リクエストのたびに動いてるとポート枯渇になってエラったりする
    * N+1クエリ問題

### RDBMS／Cache

* 心にいつもB+Treeを

## 最後に

### 大事なこと

* 初期状態をコミットしていつでも戻せるようにしておく
* 変更を都度記録し壊れる前の状態に戻しやすくする
* 前日はよく寝る
* 諦めたらそこで終了

---

ref: 福井技術者の集い #4 俺なりのISUCONとかの戦い方 / rch850
https://youtu.be/YLiMh_-hTQA

## 開始5分

* ポータルサイトを開き様子を見る
    * 「俺インスタンス立てるからルール読んどいて」
    * 「おk」
    * 「人数分立てるから好き勝手遊んで」

## 開始45分

* 役割分担を決める
    * ベンチマークのボトルネック調査
        * nginxでrequest_timeをログに出して遅いリクエストを調べる
    * Rubyのコード見て最適化
        * ざっとクエリ見てインデックス張る
        * 段階ごとの処理時間をログに出す
        * Rubyのコードをクエリに書き換える
            * 単純なSELECTしかしてなくてRubyで全部配列を料理しちゃってるやつ
            * 「これSQLで書けるやつだ」
        * 「○ソコードを潰す作業」
            * 平常時「○ソコードだ！○ソッ！」ISUCON「○ソコードだ！やったぜ！」
    * nginx, unicornの最適化
        * unicornのworker_processesを増やす（20程度）
        * nginxのworker_processesを増やす（4）

## 開始2時間半頃

* 3000出てトップに
* 昼食は人に買い出しさせた

## その後、試合終了まで

* MySQLのチューニング
    * メモリを使うようにする
        * innodb_buffer_pool_size
        * innodb_sort_buffer_size
    * 遅いクエリを探すためにslow logをmysqldumpslowにかける
    * 「サブクエリなんとかならんかなー」
* アプリケーション側
    * erb内のクエリを最適化
    * 数だけあればいいのにSELECT *してたところをCOUNTに
    * 友達関係は常に両思いだから片方にだけチェック