ISUCON9予選
練習のために解いてみる
環境構築
code:zsh
# virtualboxをたちあげておく
# local
$ cd vagrant-isucon/isucon9-qualifier-standalone
$ vagrant up
# 30分ぐらい待つ
# 何事もなければ完了
# 以降、vagrant-isucon/isucon9-qualifier-standalone directoryで以下を実行すると仮想マシン内に入れる
$ vagrant ssh
vagrant upした時点でアプリケーションは起動している
code:zsh
# local
# IPアドレスの確認
$ vagrant ssh -c "hostname -I | cut -d' ' -f2" 2>/dev/null
172.28.128.7
# localのブラウザで開く
https://gyazo.com/dd27b9242ec171cbe046e232e4e22a74
code:zsh
# in VM
$ cd ~/isucari
$ bin/benchmarker
2020/07/19 16:25:42 main.go:180: === final check ===
2020/07/19 16:25:42 main.go:212: 1710 0
{"pass":true,"score":1710,"campaign":0,"language":"go","messages":[]}
Rubyのプロセスを動かす
code:zsh
# in VM
# golangのserviceが走っていることを確認
$ systemctl | grep go
isucari.golang.service
# Rubyに切り替える
$ sudo systemctl stop isucari.golang.service
$ sudo systemctl disable isucari.golang.service
$ sudo systemctl start isucari.ruby.service
$ sudo systemctl enable isucari.ruby.service
# プロセス再起動
$ sudo systemctl restart isucari.ruby.service
systemdでserviceとして登録しているisucari.ruby.serviceの在り処を探す code:zsh
# in VM
$ cat /etc/systemd/system/isucari.ruby.service
Description = isucon9 qualifier main application in ruby
WorkingDirectory=/home/isucon/isucari/webapp/ruby
EnvironmentFile=/home/isucon/env.sh
ExecStart = /home/isucon/local/ruby/bin/bundle exec rackup -p 8000
Restart = always
Type = simple
User = isucon
Group = isucon
WantedBy = multi-user.target
ExecStartにあるコマンドをsudoで以下に書き換える
ExecStart = /home/isucon/local/ruby/bin/bundle exec rackup -p 8000 --host 0.0.0.0
code:zsh
# in VM
$ sudo systemctl restart isucari.ruby.service
Warning: The unit file, source configuration file or drop-ins of isucari.ruby.service changed on disk. Run 'systemctl daemon-reload' to reload units.
$ sudo systemctl daemon-reload
$ sudo systemctl restart isucari.ruby.service
# restartする
gitの設定
Vagrant内にgitはinstall済
GitHub
private repositoryを作っておく
code:zsh
$ cd /home/isucon/isucari
$ git init
# 署名情報
$ git config --global user.email "you@example.com"
$ git config --global user.name "Your Name"
# access tokenを記録させるよう設定
$ git config --global credential.helper cache
$ git config --global credential.helper 'cache --timeout=86400'
$ git commit --allow-empty -m "initial commit"
$ git push -u origin master
# ここで入力したaccess tokenはcacheされる
設定ファイルもgit管理
systemdの起動コマンド
code:zsh
$ cd /home/isucon/isucari
$ mkdir systemd
$ sudo cp /etc/systemd/system/isucari.ruby.service systemd/
$ sudo rm /etc/systemd/system/isucari.ruby.service
$ sudo ln -s /home/isucon/isucari/systemd/isucari.ruby.service /etc/systemd/system/isucari.ruby.service
$ sudo systemctl restart isucari.ruby.service
マシン調査
code:zsh
# CPUは一個だけ
$ grep processor /proc/cpuinfo
processor : 0
# Memoryは1G、Swapあり
$ free -m
total used free shared buff/cache available
Mem: 985 421 142 0 421 416
Swap: 979 41 938
# 実行中のプロセスを確認
$ ps auxf
# or
$ pstree
├─agetty
├─atd
├─cron
├─dbus-daemon
├─lvmetad
├─networkd-dispat───{networkd-dispat}
├─nginx───nginx
├─rpcbind
├─sshd───sshd───sshd───bash───sudo───bash───pstree
├─systemd───(sd-pam)
├─systemd-journal
├─systemd-logind
├─systemd-network
├─systemd-resolve
├─systemd-udevd
└─uuidd
MySQL基本操作
DB初期化スクリプト /home/isucon/isucari/webapp/sql
00_create_database.sql にuserやpasswordが記載されている
CREATE TABLE文などもあるのでindexの状態とかもわかる
code:sql
# in VM
$ cat webapp/sql/00_create_database.sql
DROP DATABASE IF EXISTS isucari;
CREATE DATABASE isucari;
DROP USER IF EXISTS 'isucari'@'localhost';
CREATE USER 'isucari'@'localhost' IDENTIFIED BY 'isucari';
GRANT ALL PRIVILEGES ON isucari.* TO 'isucari'@'localhost';
DROP USER IF EXISTS 'isucari'@'%';
CREATE USER 'isucari'@'%' IDENTIFIED BY 'isucari';
GRANT ALL PRIVILEGES ON isucari.* TO 'isucari'@'%';
$ mysql -u isucari -p
Enter password:
# 設定確認をCLIからやる
$ mysql -u isucari -p -e 'SHOW variables LIKE "%max_connections%";'
# 環境変数にpasswordを設定しておくと-pなしでいちいち聞かれなくて楽
$ export MYSQL_PWD=isucari
$ mysql -u isucari -e 'SHOW variables LIKE "%max_connections%";'
code:sql
mysql> use isucari
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------------+
| Tables_in_isucari |
+-----------------------+
| categories |
| configs |
| items |
| shippings |
| transaction_evidences |
| users |
+-----------------------+
6 rows in set (0.00 sec)
# indexを確認できる
mysql> show index from users;
# create table文を確認できる
mysql> SHOW CREATE TABLE users;
ベンチマーク
mysqldに負荷が集まっているがbundle (Puma) プロセスもそれなりに負荷がかかっていることがわかる
code:zsh
# in VM
$ top
$ bin/benchmarker
# mysqldが頑張っている
top - 12:16:36 up 10:44, 2 users, load average: 4.42, 1.29, 0.56
Tasks: 103 total, 1 running, 56 sleeping, 0 stopped, 0 zombie
%Cpu(s): 23.1 us, 3.1 sy, 0.0 ni, 71.4 id, 1.4 wa, 0.0 hi, 1.0 si, 0.0 s
KiB Mem : 1008784 total, 64368 free, 808064 used, 136352 buff/cache
KiB Swap: 1003516 total, 960252 free, 43264 used. 61188 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
22671 mysql 20 0 1166088 350724 10224 S 17.2 34.8 0:26.78 mysqld
22385 isucon 20 0 751492 101028 5556 S 9.2 10.0 0:42.43 bundle
22704 isucon 20 0 833880 295336 6060 S 2.6 29.3 0:03.59 benchmark+
400 root 19 -1 119612 12156 11588 S 0.3 1.2 0:02.04 systemd-j+
MySQL slow queries
code:sql
# 初期設定を確認
mysql> show variables like 'slow%';
+---------------------+---------------------------------+
| Variable_name | Value |
+---------------------+---------------------------------+
| slow_launch_time | 2 |
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/vagrant-slow.log |
+---------------------+---------------------------------+
3 rows in set (0.00 sec)
mysql> show variables like 'long%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.01 sec)
code:zsh
$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
slow_query_log = 1
long_query_time = 2
$ sudo systemctl restart mysql.service
# 再起動後にもう一度 show variables すると値が変わっている
$ bin/benchmarker
$ sudo mysqldumpslow -s t /var/lib/mysql/vagrant-slow.log
Reading mysql slow query log from /var/lib/mysql/vagrant-slow.log
Count: 4 Time=1.38s (5s) Lock=0.00s (0s) Rows=49.0 (196), isucariisucari@localhost SELECT * FROM items WHERE status IN ('S', 'S') AND (created_at < 'S' OR (created_at <= 'S' AND id < 'S')) ORDER BY created_at DESC, id DESC LIMIT N
# 未省略
1秒以上かかるとても遅いのはこれだけとわかる
EXPLAINしてみる
indexが使われず、type=ALLでフルスキャンされている
code:sql
mysql> EXPLAIN SELECT * FROM items WHERE status IN ('S', 'S') AND (created_at < 'S' OR (created_at <= 'S' AND id < 'S')) ORDER BY created_at DESC, id DESC LIMIT 1000;
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| 1 | SIMPLE | items | NULL | ALL | PRIMARY | NULL | NULL | NULL | 43797 | 16.29 | Using where; Using filesort |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
1 row in set, 4 warnings (0.00 sec)
indexを貼ってみる
利用されるようになったことを確認する
code:sql
mysql> CREATE INDEX created_at ON items (created_at);
mysql> EXPLAIN SELECT * FROM items WHERE status IN ('S', 'S') AND (created_at < 'S' OR (created_at <= 'S' AND id < 'S')) ORDER BY created_at DESC, id DESC LIMIT 1000;
+----+-------------+-------+------------+-------+--------------------+------------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+--------------------+------------+---------+------+------+----------+-------------+
| 1 | SIMPLE | items | NULL | index | PRIMARY,created_at | created_at | 5 | NULL | 1000 | 16.29 | Using where |
+----+-------------+-------+------------+-------+--------------------+------------+---------+------+------+----------+-------------+
1 row in set, 6 warnings (0.00 sec)
ただしconsoleからCREATE INDEXして作成されたindexは#POST /initializeのタイミングでリセットされてしまう
/home/isucon/isucari/webapp/sql/01_schema.sql あたりの初期化スクリプトを変更する
long_query_time=0にしてすべてのクエリを出力してみる
-s tでクエリの合計時間順にソート
チリも積もれば遅くなるクエリが見える
categoriesは固定値なのでオンメモリで持っても良さそう
code:sql
$ sudo mysqldumpslow -s t -t 5 /var/lib/mysql/vagrant-slow.log
Reading mysql slow query log from /var/lib/mysql/vagrant-slow.log
Count: 73198 Time=0.00s (85s) Lock=0.00s (3s) Rows=1.0 (73198), isucariisucari@localhost SELECT * FROM categories WHERE id = 'S'
Count: 39112 Time=0.00s (49s) Lock=0.00s (2s) Rows=1.0 (39112), isucariisucari@localhost SELECT * FROM users WHERE id = 'S'
Count: 63 Time=0.61s (38s) Lock=0.00s (0s) Rows=49.0 (3087), isucariisucari@localhost SELECT * FROM items WHERE status IN ('S', 'S') AND (created_at < 'S' OR (created_at <= 'S' AND id < 'S')) ORDER BY created_at DESC, id DESC LIMIT N
Count: 142 Time=0.24s (33s) Lock=0.00s (0s) Rows=24.6 (3490), isucariisucari@localhost SELECT * FROM items WHERE seller_id = 'S' AND status IN ('S', 'S', 'S') ORDER BY created_at DESC, id DESC LIMIT N
Count: 199 Time=0.17s (33s) Lock=0.00s (0s) Rows=49.0 (9751), isucariisucari@localhost SELECT * FROM items WHERE status IN ('S', 'S') AND category_id IN ('S','S','S','S','S') AND (created_at < 'S' OR (created_at <= 'S' AND id < 'S')) ORDER BY created_at DESC, id DESC LIMIT N
-s at クエリの平均時間でソート
code:sql
$ sudo mysqldumpslow -s at -t 5 /var/lib/mysql/vagrant-slow.log
Reading mysql slow query log from /var/lib/mysql/vagrant-slow.log
Count: 63 Time=0.61s (38s) Lock=0.00s (0s) Rows=49.0 (3087), isucariisucari@localhost SELECT * FROM items WHERE status IN ('S', 'S') AND (created_at < 'S' OR (created_at <= 'S' AND id < 'S')) ORDER BY created_at DESC, id DESC LIMIT N
Count: 7 Time=0.38s (2s) Lock=0.00s (0s) Rows=49.0 (343), isucariisucari@localhost SELECT * FROM items WHERE status IN ('S', 'S') ORDER BY created_at DESC, id DESC LIMIT N
Count: 103 Time=0.28s (28s) Lock=0.00s (0s) Rows=49.0 (5047), isucariisucari@localhost SELECT * FROM items WHERE status IN ('S', 'S') AND category_id IN ('S','S','S','S') AND (created_at < 'S' OR (created_at <= 'S' AND id < 'S')) ORDER BY created_at DESC, id DESC LIMIT N
Count: 142 Time=0.24s (33s) Lock=0.00s (0s) Rows=24.6 (3490), isucariisucari@localhost SELECT * FROM items WHERE seller_id = 'S' AND status IN ('S', 'S', 'S') ORDER BY created_at DESC, id DESC LIMIT N
Count: 7 Time=0.21s (1s) Lock=0.00s (0s) Rows=49.0 (343), isucariisucari@localhost SELECT * FROM items WHERE status IN ('S','S') AND category_id IN ('S','S','S','S') ORDER BY created_at DESC, id DESC LIMIT N
ログをローテーションしないとslow query logが貯まり続けるので注意
$ : > slow.logとかvimで雑に空にしても良い
itemsのseller_id, buyer_id, created_atにindexを貼ると、スコアが2000点に乗ったので有効
topコマンドで見た感じがbundleプロセスに負荷が寄ってきた
mysqldumpslowで遅いクエリを見てもDDLばかりになってきた アプリケーションの改善にいけそう
NewRelic
フォームから申し込み、アカウントを作る
過去に利用したことのあるメールアドレスを入力すると永遠にメールが届かない問題がある
Gmailのエイリアス使ったら回避できた
ログインすると言語ごとのセットアップ手順があるのでほぼこの通りに進めていく
gemのinstall
code:/home/isucon/isucari/webapp/ruby/Gemfile
+ gem 'newrelic_rpm'
code:zsh
$ /home/isucon/local/ruby/bin/bundle install
applicationからgemの読み込み
code:/home/isucon/isucari/webapp/ruby/lib/isucari/web.rb
require 'json'
require 'securerandom'
require 'sinatra/base'
+ require 'newrelic_rpm'
require 'mysql2'
newrelic.ymlを setup page からダウンロードし、application root (/home/isucon/isucari/webapp/ruby/)に置く
ベンチマークを実行する
code:zsh
$ sudo systemctl restart isucari.ruby.service
$ bin/benchmarker
NewRelicのconsoleから確認できる!
rackupで起動している事に起因
ohbarye.icon なぜこいつらとnewrelic_rpmを組み合わせると落ちるのかはわからないのでフォーラムに投げてみる
code:json
$ bin/benchmarker
2020/07/21 08:58:07 main.go:129: cause error!
{"pass":false,"score":0,"campaign":0,"language":"ruby","messages":"POST /login: got response status code 500; expected 401","GET /settings: got response status code 500; expected 200","GET /settings: got response status code 500; expected 200","GET /items/18697.json: got response status code 500; expected 200","POST /login: got response status code 500; expected 200","GET /items/50000.json: got response status code 500; expected 200","GET /upload/336bd3af5fbb247a55354184a3dfb35f.jpg: got response status code 500; expected 200","POST /items/edit: got response status code 500; expected 200 (item_id: 409)"} code:stacktrace
"status code: 500; body: RuntimeError: can't add a new key into hash during iteration
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:31:in `accept'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:46:in `preferred_type'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/show_exceptions.rb:92:in `prefers_plain_text?'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/show_exceptions.rb:26:in `rescue in call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/show_exceptions.rb:21:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/newrelic_rpm-6.12.0.367/lib/new_relic/agent/instrumentation/middleware_tracing.rb:101:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:194:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/newrelic_rpm-6.12.0.367/lib/new_relic/agent/instrumentation/middleware_tracing.rb:101:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:1950:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:1502:in `block in call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:1729:in `synchronize'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:1502:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/newrelic_rpm-6.12.0.367/lib/new_relic/agent/instrumentation/middleware_tracing.rb:101:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/tempfile_reaper.rb:15:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/lint.rb:49:in `_call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/lint.rb:37:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/show_exceptions.rb:23:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/common_logger.rb:33:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/sinatra-2.0.7/lib/sinatra/base.rb:231:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/chunked.rb:54:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/content_length.rb:15:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/puma-4.1.0/lib/puma/configuration.rb:228:in `call'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/puma-4.1.0/lib/puma/server.rb:664:in `handle_request'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/puma-4.1.0/lib/puma/server.rb:467:in `process_client'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/puma-4.1.0/lib/puma/server.rb:328:in `block in run'
/home/isucon/isucari/webapp/ruby/.bundle/ruby/2.6.0/gems/puma-4.1.0/lib/puma/thread_pool.rb:135:in `block in spawn_thread'"
回避策(ベンチマークが完走するやり方)
rackup時に余分なmiddlewareを外すか、シングルスレッドで動かす
ただしベンチマークの結果は悪くなった
code:/etc/systemd/system/isucari.ruby.service
ExecStart = /home/isucon/local/ruby/bin/bundle exec rackup -s WEBrick -p 8000 --host 0.0.0.0
environmentをdevelopment以外にする
ベンチマークへの影響なし
code:/etc/systemd/system/isucari.ruby.service
ExecStart = /home/isucon/local/ruby/bin/bundle exec rackup -E production -p 8000 --host 0.0.0.0
ただしnewrelic.ymlの設定次第では環境 (この場合はRACK_ENVでもあり、-E optionで指定する値) ごとにapp_nameが変わるので注意
計測結果も別アプリケーションとして表示される
My Application (Development) => -E optionなし = デフォルトのdevelopment
My Application => development, staging 以外
https://gyazo.com/3cc388af3e4bbd38ecfb91bdc50b5c1e
code:/etc/systemd/system/isucari.ruby.service
ExecStart = /home/isucon/local/ruby/bin/bundle exec puma -b tcp://0.0.0.0:8000
https://gyazo.com/5f8a5a340851c545784dd80a7b220e91
initialize用のendpoint
実行に10秒以上かかるので邪魔
https://gyazo.com/c3fc83060c28a36036a12f032f89af9b
newrelic_ignore directiveで除外可能
code:/home/isucon/isucari/webapp/ruby/lib/isucari/web.rb
newrelic_ignore '/initialize'
License keyの取り扱い
デフォルトではnewrelic.ymlに記載されているが公開されるのは好ましくない
license_key: xxxxxを消しておく
アプリケーション起動時にsystemdから読まれるところに書いておく
code:/home/isucon/env.sh
NEW_RELIC_LICENSE_KEY=xxxxx
改善ログ
初期状態
{"pass":true,"score":1510,"campaign":0,"language":"ruby","messages":[]}
index追加
code:01_schema.sql
CREATE INDEX created_at ON items (created_at);
CREATE INDEX seller_id ON items (seller_id);
CREATE INDEX buyer_id ON items (buyer_id);
{"pass":true,"score":1810,"campaign":0,"language":"ruby","messages":[]}
shippment/status呼び出しをPOSTからGETへ
{"pass":true,"score":2010,"campaign":0,"language":"ruby","messages":[]}
categoriesをインメモリにしてfindのN+1地獄を回避
{"pass":true,"score":2620,"campaign":0,"language":"ruby","messages":[]}
items.map内のusers N+1を回避
{"pass":true,"score":3210,"campaign":0,"language":"ruby","messages":[]}
/user/transactions.jsonで外部APIの呼び出しは不要なので止める
{"pass":true,"score":7860,"campaign":0,"language":"ruby","messages":[]}
indexを複合indexに修正した
code:01_schema.sql
CREATE INDEX created_at ON items (created_at);
CREATE INDEX seller_id ON items (seller_id, created_at);
CREATE INDEX buyer_id ON items (buyer_id, created_at);
CREATE INDEX category_id ON items (category_id, created_at);
{"pass":true,"score":9160,"campaign":0,"language":"ruby","messages":[]}
campaign=1にした
リクエストが爆増して耐えられなくなった
APIをスケールアウトしたいがstandalone構成だと難しい
{"pass":true,"score":7660,"campaign":1,"language":"ruby","messages":["GET /users/500.json: リクエストに失敗しました(タイムアウトしました)","POST /login: リクエストに失敗しました(タイムアウトしました)","POST /ship_done: リクエストに失敗しました (item_id: 50019)(タイムアウトしました)"]}
戻した
/user/transactions.jsonでN+1を解消
もっと伸びるはずが、campaign以降はスコアが上がらなくなってしまった
{"pass":true,"score":9160,"campaign":0,"language":"ruby","messages":[]}
/user/transactions.jsonでORクエリを解消
なぜか下がった…
New Relicを見るとこの時点でボトルネックは/buy
{"pass":true,"score":8960,"campaign":0,"language":"ruby","messages":[]}
/buyでuserをselect for updateする必要ない
{"pass":true,"score":9160,"campaign":0,"language":"ruby","messages":[]}
/buyでリクエストを並列化
{"pass":true,"score":9460,"campaign":0,"language":"ruby","messages":[]}
/items/:item_id.jsonでseller, buyerをjoinで一発で取ってくるようにする
ようやく予選突破スコアまでいった 🎉
{"pass":true,"score":9660,"campaign":0,"language":"ruby","messages":[]}
/items/:item_id.jsonでtransaction_evidence, shippingをjoinで一発で取ってくるようにする
変わらず
{"pass":true,"score":9660,"campaign":0,"language":"ruby","messages":[]}
campaign=1にした
耐えられないのが/loginだけになったのでログイン用の別サーバを用意するとかできたらいけるかも
とりあえず戻す
{"pass":true,"score":8760,"campaign":1,"language":"ruby","messages":["POST /login: リクエストに失敗しました(タイムアウトしました)"]}
New Relicをオフにする
require 'newrelic_rpm'を消す
めっちゃ上がった!
{"pass":true,"score":12260,"campaign":0,"language":"ruby","messages":[]}
参考