Skip to content

Instantly share code, notes, and snippets.

@koyo-miyamura
Last active November 21, 2021 00:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koyo-miyamura/6467285f7acaed0bc41f3279aa6fbb12 to your computer and use it in GitHub Desktop.
Save koyo-miyamura/6467285f7acaed0bc41f3279aa6fbb12 to your computer and use it in GitHub Desktop.
isucon10.md

ISUCON カンペ集

最初にやること

問題文を熟読し、スキーマ/アプリをざっくり把握! SQL 使ってるとこ抜き出しとかしてもいいかもね。

vscode ssh

https://www.tweeeety.blog/entry/20140121/1390275336

定番設定

nginx

access_log を出す

log_format ltsv "time:$time_local"
                "\thost:$remote_addr"
                "\tforwardedfor:$http_x_forwarded_for"
                "\treq:$request"
                "\tstatus:$status"
                "\tmethod:$request_method"
                "\turi:$request_uri"
                "\tsize:$body_bytes_sent"
                "\treferer:$http_referer"
                "\tua:$http_user_agent"
                "\treqtime:$request_time"
                "\tcache:$upstream_http_x_cache"
                "\truntime:$upstream_http_x_runtime"
                "\tapptime:$upstream_response_time"
                "\tvhost:$host";
access_log /var/log/nginx/access.log ltsv;
$ cat /etc/nginx/nginx.conf
worker_processes  1;

events {
  worker_connections  10000;
}

http {
  include     mime.types;
  sendfile    on;
  tcp_nopush  on;
  tcp_nodelay on;
  etag        off;
  ; アプリケーションがUNIXドメインソケットであれば
  upstream app {
    server unix:/dev/shm/app.sock;
  }

  server {
    location / {
      proxy_pass http://app;
    }
    location ~ ^/(stylesheets|images)/ {
      open_file_cache max=100;
      root /home/isucon/webapp/public;
    }
  }
}
  • https://diary.sorah.jp/2017/10/23/isucon7q によると
    • add_header Cache-Control "public, max-age=86400"; とかclient_max_body_size 20M; とかもあっていいかも?
    • worker_processes auto; worker_rlimit_nofile 4096; keepalive_timeout 120s; とかもあるかも
  • sudo nginx -s reload とか sudo service nginx restart で再起動忘れずに!

mysql

[mysqld]
slow_query_log=1
slow_query_log_file=/var/lib/mysql/slow.log’
long_query_time=0.1

もしくは

set global slow_query_log=1;
set global slow_query_log_file=/var/lib/mysql/slow.log';
set global long_query_time=0.1;

log-queries-not-using-indexes はなくていいと思う

$ cat /etc/my.cnf
innodb_buffer_pool_size = 1G
innodb_flush_log_at_trx_commit = 0
innodb_flush_method=O_DIRECT

sudo service mysqld restart とかで再起動

MySQL データサイズ確認

SELECT table_name, engine, table_rows, avg_row_length, floor((data_length+index_length)/1024/1024) as allMB, floor((data_length)/1024/1024) as dMB, floor((index_length)/1024/1024) as iMB FROM information_schema.tables WHERE table_schema=database() ORDER BY (data_length+index_length) DESC;

OS

$ cat /etc/sysctl.conf
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.ip_local_port_range = 10000 65000
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
  • fs.file-max = 100000 もありかも
  • cat /etc/sysctl.d/99-sysctl.conf のパターンもある
  • sudo /sbin/sysctl -p とかで反映

redis

tcp-keepalive 60

save 900 1
save 300 10
save 120 20000

maxclients 10000

appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite no

ベンチ時

以下のようなスクリプトで再起動しつつスローログなど移動するの大事 設定ファイルの更新後再起動忘れがちなので注意

set -ex

if [ -f /var/lib/mysql/mysqld-slow.log ]; then
    sudo mv /var/lib/mysql/mysqld-slow.log /var/lib/mysql/mysqld-slow.log.$(date "+%Y%m%d_%H%M%S")
fi
if [ -f /var/log/nginx/access.log ]; then
    sudo mv /var/log/nginx/access.log /var/log/nginx/access.log.$(date "+%Y%m%d_%H%M%S")
fi
sudo systemctl restart mysql
# sudo service memcached restart
sudo systemctl restart nginx

MySQL slowlog

http://naoberry.com/tech/slowquery/

  • ロック待ちは long_query_time の算出時間に含まれない

設定方法

my.conf に書く場合

[mysqld]
slow_query_log=1
slow_query_log_file=/var/lib/mysql/slow.log’
long_query_time=0.1

long_query_time は 0.1 くらいがいいのではないか(持論)

mysql 中で行う場合

set global slow_query_log=1;
set global slow_query_log_file=/var/lib/mysql/slow.log';
set global long_query_time=0.1;

pt-query-digest

mysqldumpslow

  • 基本 pt-query-digest でいいが、使えなかった場合こっちでも代用できる
    • mysqldumpslow /var/log/mysql/mysql-slow.sql でとりあえず OK

dstat

オススメ alias

if [ -x /usr/bin/dstat ]; then
   alias dstat-full='dstat -tclmdrn'
   alias dstat-mem='dstat -tclm'
   alias dstat-cpu='dstat -tclr'
   alias dstat-net='dstat -tclnd'
   alias dstat-disk='dstat -tcldr'
fi

以下のようにすると出力もできる

dstat-full --output /home/hoge/dstat_date "+%Y-%m-%d".csv

オプション 説明
t 時間表示
T epoch time 表示する
c CPU 使用率
l ロードアベレージ
m メモリ使用量
r IO 回数
n ネットワーク IO(単位は B/s)
d Disk IO
c CPU 使用率

alp

アクセスプロファイラ http://kazuki229.hatenablog.com/entry/2017/09/29/003314

cat /var/log/nginx/access.log | alp ltsv

kataribe

アクセスプロファイラ。今回は alp でいいかなと思うが一応。 https://github.com/matsuu/kataribe

  wget https://github.com/matsuu/kataribe/releases/download/v0.4.1/kataribe-v0.4.1_linux_amd64.zip -O kataribe.zip
  unzip -o kataribe.zip
  sudo mv kataribe /usr/local/bin/
  sudo chmod +x /usr/local/bin/kataribe
  rm kataribe.zip
  kataribe -generate

Go のプロファイラ

  import (
    _ "net/http/pprof"
  )

	go func() {
		log.Println(http.ListenAndServe("0.0.0.0:6060", nil))
	}()
  • png で結果を吐き出す GO111MODULE=on go tool pprof -png -output pprof.png http://localhost:6060/debug/pprof/profile
  • WebUI 情報量が多いので良さそう GO111MODULE=on go tool pprof -http=":8888" http://localhost:6060/debug/pprof/profile
    • すでに一回実行するとファイルが生成されるのでそれ指定してもいい GO111MODULE=on go tool pprof -http=":8888" /Users/miyamura-koyo/pprof/pprof.samples.cpu.005.pb.gz
    • sudo yum install graphviz しないと動かないかも

MySQL パーティショニング

rsync

ISUCON 過去問ブログ

第 9 回

第 8 回

その他

その他よくあるパターン集

  • 再起動試験忘れるのあるあるなので、最後はそれ
  • HTTP/2 にする
    • 問題によっては難しい場合もある
  • 複数台構成
    • DB サーバを分けるのが定番
    • 変わり種としては重い API だけ特定のサーバに振り分けるとかもあるっぽい
  • bcrypt みたいな特定の重い処理を緩和する
    • コスト(ストレッチング回数) 減らしていいんなら減らす
  • MySQL コネクションを使い回す
  • N+1
  • メモリにのせる
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment