cheat sheets for isucon3 middleware settings
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
isucon2
00.machine.md
00.metrics.md
01.aws.md
01.ssh.md
02.iptables_selinux.md
02.kernel.md
03.yum_repo.md
04.tmux.md
05.node.md
05.python.md
05.ruby.md
05.ruby_metrics.md
05.ruby_newrelic.md
06.mysql_5.5.md
06.mysql_5.6.md
06.mysql_repl.md
06.mysql_stat.md
06.mysql_tmc.md
06.mysql_tmpfs.md
09.unicorn.md
10.nginx.md
11.varnish.md
12.redis.md
12.redis_resque.md
12.redis_ruby.md
13.daemontools.md
14.golang.md
README.md

README.md

isucon3_prepare

ISUCON3 レギュレーションと予選当時の流れ

当日の行動

  • 予選 10月5日(土) 10:00 - 18:00 => 10月6日(日) 10:00 - 18:00 に変更しました
  • 遅くとも 09:30 にはヒカリエに集まる. 席を近くにする(モニタは借りればよい.休みなので使ってない)
  • ご飯は食べておく and 飲み物とか買っておく

次回に向けて(反省)

直せそうな所を見つけてすぐ直すよりも、一旦まとめて戦略を錬ってガッとやる方が上位にいけるっぽい 簡単な改修ポイントがみつかってもまだ手を出さず、最初は洗い出しに専念すること!!

  • AMI3台立ち上げる。1台は本番機でインフラ担当が扱う。公開鍵を渡して登録してもらう。

  • 本番機を初期設定する

  • レギュレーションを読む

  • メトリクスを取る仕込みを入れて time コマンドかまして1回ベンチ通す(ベンチ1回に何秒かかるか見る)

  • mysql で log-queries-not-using-indexes を出すようにしておく

  • HTTPリクエストのメトリクスをとえるプロファイラを仕込む (nginx のログで見る手もある)

  • SQLクエリのメトリクスをとれるプロファイラを仕込む (long_query_time = 0 で slow.log 出しておき、mysqlslowdump という手もある)

  • テンプレートエンジンのメトリクスをとれるプロファイラを仕込む

  • lsof してアプリがどこにアクセスしているのかとっておく

  • vmstat の結果をとっておく

  • iostat の結果をとっておく

  • テーブルのスキーマ、インデックス情報をとっておく (show create table memos, explain ....)

  • https://gist.github.com/sonots/0a6211ea5bb5fc1f795c

  • 追加: データの特性をみる

    • どのデータが増えてどのデータは固定なのか. 増えるとして何 rows, bytes ぐらい増えるのか
    • 初期データは何 rows, bytes ぐらいなのか
  • 追加: benchmarker の動きをみる

    • どの endpoint にどの順番でアクセスしてくるのか。どのアクセス群が一連の流れなのか(あとはそのループのはず)

    • リクエストヘッダをみる。リクエストヘッダには運営からのヒントが書かれている

      • ToDo: ログに吐くようにしておくべきか
  • 本番機をイメージ化して共有する(待ち時間発生。その間に下)

  • メトリクスの結果とコードを見てチューニング箇所を考える

  • アプリの画面を触りながら(Chrome の Developer Tools 開きながら)議論し、戦略を練る。

  • (一人)用意しておいたミドルウェアの設定ファイルを適用していく

  • (二人)ガッとやる

  • 計測する. 外の情報にもアンテナを貼っておく(途中でレギュレーションに補足が入ったりする)

  • 追加: 明確なチューニングポイントが見えなくなってきた場合、コードレベルでのプロファイリングが必要になってくる(それぐらいしかやることが残っていない)

    • コードにプロファイラを仕込む(golang: pprof, ruby: stackprof)
    • フレームワークが遅かったらフレームワークを外すなど
  • 追加: benchmarker の隙を付く、レギュレーションの隙をつく

    • strings benchmarker、tcpdump
    • 遅い所はあえて fail したら得点あがるかもとか
    • このレスポンスヘッダを benchmarker は解釈するかもとか. リダイレクトを省けるのでは、とか.
    • benchmarker 内部で時間かかってそうだから、そこをあえて fail させて飛ばせないかとか

役に立つかもしれない情報

クエリチューニング:

  • http://www.slideshare.net/kazeburo/isucon-summerclass2014action2final
  • まずは検索カラムに index を貼る
  • SELECT のカラムを * から必要なカラムに絞る。少数ならば index 貼ってしまって、covering index にしてしまう
  • LIMIT ? OFFSET ? は IN に置き換える
  • N+1 クエリはまとめて取得できるように書き換える
    • 典型例: 二つのテーブルを合体するためのN+1クエリ => Joinに直す
  • なぜか index が利かなくて実行計画がおかしい場合は、select ... from table force index(index_name); とする。

アイデア:

  • アプリに newrelic か rack-mini-profiler 仕込んだほうがよさそう

  • rubinius への置き換え => 使ったことないのでエラー出た時どうしたらいいかわからん

  • tmpfs のファイルに書き込んで簡易にプロセス間メモリ共有

  • mysql のデータファイルを tmpfs においたらはやそう

    • レギュレーションの「サーバの設定およびデータ構造は任意のタイミングでのサーバ再起動に耐えること」にひっかかるのでだめっぽい T T
    • シャットダウン時にディスクにおいて、起動時にディスクから tmpfs に cp するようにすればいいんじゃないのかな
    • 実際にやってみたが速くはなったが、varnish のほうが銀の弾丸度では上だな。アプリの処理を丸っと省けるからな。

cf. http://blog.nomadscafe.jp/2012/11/isucon2-5.html

  • kazeburo さんは worker に HTML を保存させてそれを serve するようにしたらしい https://github.com/kazeburo/isucon2_hack/blob/master/perl/worker.pl
  • nginx にアクセス時に gzip 圧縮するのではなく、その HTML をあらかじめ gzip 圧縮して配信したらしい
  • トラッフィク多すぎたので delay を入れたとな ...

cf. http://www.seeds-std.co.jp/seedsblog/163.html

memcached の中に入ってるキーを一覧するperlワンライナー

perl -MCache::Memcached -e '$s="localhost:11211";$m=new Cache::Memcached({servers=>[$s]});$res=$m->stats("items");$i=$res->{hosts}{$s}{items};@a=split("€n",$i);while(){if($_=~/items:([0-9]+)/){$s{$1}=$_}};foreach $key (keys %s){$cm="cachedump $key 100";$res=$m->stats($cm);print "--- €n".$cm."€n";print $res->{hosts}{$s}{$cm}}'

再起動時にキャッシュに突っ込むシェルスクリプト

#!/bin/sh

for i in `seq 1 1 3000`
do
    wget http://app01/article/$i -O -
done

デプロイ. てっとりはやく rsync でいいかもね => git pull で

#!/bin/sh
rsync -Irp --exclude ".git" --progress . $HOST:isucon/webapp/ruby/
ssh -t $HOST sudo /etc/init.d/supervisord restart