あいつの日誌β

働きながら旅しています。

ISUCON4 予選の復習を終えました

ミドルウェアのチューニングでどれぐらい数値があがるのかを検証してみました。

なお、本エントリーにベンチマークの数値が出ていますがこの計測は時々インスタンスを停止、再開させているのでインスタンスガチャ的な数値の変動も含まれております。

workload

何もしていない状態でも workload の数値を上げると点数が上がります。

start bench workload: 1
13:38:23 type:score     success:5950    fail:0  score:1286
start bench workload: 2
13:39:53 type:score     success:9400    fail:0  score:2032
start bench workload: 3
13:41:23 type:score     success:11090   fail:0  score:2396
start bench workload: 4
13:42:53 type:score     success:11610   fail:0  score:2510
start bench workload: 5
13:44:23 type:score     success:11900   fail:0  score:2573
start bench workload: 6
13:45:53 type:score     success:11550   fail:0  score:2498

ISUCON の予選では同じサーバーに WEB と DB のプロセスが同居していますが、それと同時にベンチマークのプロセスも一緒です。

この予選ではいかにベンチマークに CPU のリソースを割り当てる事ができるか、というところもポイントなので最初から workload の数値を上げて挑むと良いのではないでしょうか。

Ruby から Perl

得意な言語に切り替える。

start bench workload: 4
13:53:35 type:score     success:15680   fail:0  score:3389
start bench workload: 5
13:55:05 type:score     success:15140   fail:0  score:3273
start bench workload: 6
13:56:36 type:score     success:15091   fail:5  score:3264

unix domain socket

多少効果ありました。3way hand shake するより速いっていう理屈通り。

14:01:19 type:score     success:15730   fail:0  score:3400
start bench workload: 5
14:02:49 type:score     success:15570   fail:0  score:3365
start bench workload: 6
14:04:20 type:score     success:15525   fail:1  score:3357

starman -> starlet

うーん。状況と設定次第だと思います。

start bench workload: 4
15:36:58 type:score     success:15970   fail:0  score:3452
start bench workload: 5
15:38:29 type:score     success:15725   fail:1  score:3399
start bench workload: 6
15:39:59 type:score     success:15460   fail:0  score:3342

static file を nginx に返事させる

これは効果ある。当然と言えば当然。

start bench workload: 4
15:59:16 type:score     success:16950   fail:0  score:3663
start bench workload: 5
16:00:47 type:score     success:16030   fail:0  score:3466

DB インデックス

  • users.login のインデックスを作成
  • login_log.user_id, login_log.succeeded の複合インデックスを作成
  • login_log.ip, login_log.succeeded の複合インデックスを作成

このあたりから mysql と nginx の負荷逆転が始まる。

start bench workload: 4
16:25:22 type:score     success:136360  fail:0  score:29454
start bench workload: 5
16:26:37 type:score     success:141100  fail:0  score:30480
start bench workload: 6
16:27:52 type:score     success:146750  fail:0  score:31701
start bench workload: 7
16:29:47 type:score     success:145970  fail:0  score:31533
start bench workload: 8
16:31:01 type:score     success:147090  fail:0  score:31775
start bench workload: 9
16:32:16 type:score     success:151800  fail:0  score:32793
start bench workload: 10
16:33:31 type:score     success:152540  fail:0  score:32953

my.cnf

とりあえず効果ありそうな所を変更

innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=1G

その他色々変更しても、あんまり変わらない...

DBの負荷よりも nginx の負荷が大きい状況だったのでこの時点だとあまり意味がなかったのかも?

start bench workload: 7
13:25:45 type:score     success:149370  fail:0  score:32268
start bench workload: 8
13:27:02 type:score     success:150430  fail:0  score:32497
start bench workload: 9
13:28:19 type:score     success:146300  fail:0  score:31606
start bench workload: 10
13:29:35 type:score     success:151340  fail:0  score:32695

nginx.conf

worker_process

ISUCON3 の参加者の設定ファイルを公開している人達は worker_process が 1 の人ばかりだった気がします。

worker_process は auto にしたりとか cpu の数に合わせるのが定石かもしれませんがこの予選においてはベンチツールがほとんどのCPUを使うほうが望ましいのでチューニングが進んだ結果 worker_process は 1 になっている様です。というわけで本エントリーでも worker_process を 1 に設定します。

use epoll

まあこっちのほうがモダンって事で

start bench workload: 10
14:25:41 type:score     success:152400  fail:0  score:32922
start bench workload: 11
114:26:57 type:score    success:153558  fail:2  score:33174
start bench workload: 12
14:28:14 type:score     success:151000  fail:0  score:32623

でここで一回インスタンス落として再起動。おや、早くなってる。インスタンスガチャかな?

start bench workload: 10
12:53:26 type:score     success:161720  fail:0  score:34938
start bench workload: 11
12:54:41 type:score     success:158790  fail:0  score:34305

server_tokens off;

これ案外効果がある。一つ手間省くだけでこうも違うのか。

start bench workload: 10
13:00:01 type:score     success:166300  fail:0  score:35926
start bench workload: 11
13:01:16 type:score     success:165060  fail:0  score:35658
start bench workload: 12
13:02:31 type:score     success:167630  fail:0  score:36214

open_file_cache max=100000 inactive=20s;

これもたぶん効果があると思います。

start bench workload: 10
13:21:02 type:score     success:166610  fail:0  score:35993
start bench workload: 11
13:22:17 type:score     success:166780  fail:0  score:36028
start bench workload: 12
13:23:32 type:score     success:167490  fail:0  score:36184

セッションの保存先を RAM ディスクに変更

fujiwara組の真似をします。

http://d.hatena.ne.jp/sfujiwara/20140929/1411972115

セッションの保存先がファイル(Plack::Session::Store::File)だったのでファイルの保存先を/dev/shmに変更。というわけでちょっとだけコードをいじります。

start bench workload: 10
13:55:03 type:score     success:169440  fail:0  score:36602
start bench workload: 11
13:56:18 type:score     success:170270  fail:0  score:36782
start bench workload: 12
13:57:33 type:score     success:170920  fail:0  score:36923

このやり方はすごい参考になりました。 free コマンド使うと確かにメモリがたくさん余ってる。

ローカルポート

確かこのへんでローカルポートが枯渇し始めるので対策します。 次回 ISUCON に出場される方は最初の段階で対策しておくとよいでしょう。

ここで nginx.conf に worker_rlimit_nofile 100000; 追加したかも。

varnish

やっぱ fujiwara組の真似をします。

public ディレクトリ以下に index.html を生成して、スタイルシートと画像ファイルとこのindex.html(ただしリファラが無い場合のみ) を varnish がキャッシュするようにします。

この段階で nginx の負荷がほとんどなくなりますのでさっき行った設定どうでもよくなってます。

そして workload もちょいあげるといい感じになります。

start bench workload: 12
14:21:33 type:score     success:190041  fail:7  score:41055
start bench workload: 13
14:22:50 type:score     success:191530  fail:0  score:41377
start bench workload: 14
14:24:07 type:score     success:196703  fail:7  score:42494
start bench workload: 15
14:25:23 type:score     success:196750  fail:0  score:42505

ちなみにこの時の top

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
 3162 isucon    20   0 1072m 112m 4380 S 212.0  0.7   1:33.97 benchmarker-v2    
 3035 varnish   20   0 2074m  86m  80m S 50.3  0.6   0:24.71 varnishd           
 2561 mysql     20   0 2175m 661m 6204 S 23.6  4.4   0:37.03 mysqld             
 2711 isucon    20   0  304m  23m 4004 S 21.0  0.2   0:09.78 /home/isucon/we    
 2712 isucon    20   0  304m  23m 3996 R 19.3  0.2   0:09.90 /home/isucon/we    
 2713 isucon    20   0  304m  23m 4000 S 19.3  0.2   0:09.84 /home/isucon/we    
 2714 isucon    20   0  304m  23m 4000 S 19.3  0.2   0:09.89 /home/isucon/we  

さっきまで nginx 頑張ってたんすけどねえ。

というわけで

ソースコードほとんどいじらずに40000点を超える事ができました。 道具を上手く使うって大事すね。

ちなみに

インスタンス再起動させるとこんな結果。

start bench workload: 11
^[12:52:42 type:score   success:202960  fail:0  score:43843
start bench workload: 12
12:53:58 type:score     success:203780  fail:0  score:44022
start bench workload: 13
12:55:14 type:score     success:203885  fail:5  score:44047
start bench workload: 14
12:56:31 type:score     success:203490  fail:0  score:43961