あらすじ
復習するためにインスタンスを作成した時のメモを残します
多少は環境構築が楽になると思うので、イメージは予選の時に使用した isucon9-qualify-v1
を使用します。ただしこのイメージにはベンチマーカーが含まれていません。
この記事では以下の作業を行って webapp と benchmarker を1台のインスタンスに同梱させる方法を記します。
- ECS の準備
- make に必要な package を取得
- isucon9q のソースコードを取得
- 初期データを用意
- ベンチマーカーを make
ECS を準備
基本的には以下の作業を行えばOK
https://gist.github.com/sota1235/a7356a5909af264c1c1c840dd216c98f
Elastic Compute Service(ECS)
カスタム購入
基本構成 (必須)
価格モデル: 従量課金
リージョン: アジア東北1ゾーンA
インスタンスタイプ: ecs.sn1ne.large
共有イメージ: isucon9-qualify-v1
Ultra クラウドディスク: 40GiB
ネットワーク (必須)
ネットワーク: VPC デフォルトのまま
ネットワーク課金タイプ: トラフィック課金 100MBps
セキュリティグループ: 80, 443, 22 が空いてればOK
システム構成
キーペア: 適宜
インスタンス名: 適宜
ホスト名: 適宜 isucon9q-001 のように 1-3 の連番を振ると便利
/etc/hosts を編集
以下のような感じで編集すれば良いでしょう。
47.74.xxx.xxx isucon9q-001 isucon9.catatsuy.org
https://isucon9.catatsuy.org/ で画面が表示される事を確認し、ssh でサーバーにログインできる事を確認します。
PATH を通す
ssh でサーバーにログインします。root user のまま作業を行っています。 PATH を通したいので isucon user の bash_profile をコピーします。
cat /home/isucon/.bash_profile >> ~/.bash_profile
PATH が通っている事を確認します
exec $SHELL -l which go /home/isucon/local/go/bin/go
make に必要な package を取得 (docker, unzip)
まず unzip をインストールします
apt update apt install -y unzip
続いて Docker。以下の URL の Install using the repository
と INSTALL DOCKER ENGINE - COMMUNITY
の作業を行います。
https://docs.docker.com/install/linux/docker-ce/ubuntu/
Install using the repository
apt install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
INSTALL DOCKER ENGINE - COMMUNITY
apt update apt install -y docker-ce docker-ce-cli containerd.io
動作確認をする
docker run hello-world
isucon9q のソースコードを取得 (git clone)
この記事では /home/isucon
の直下に isucon9-qualify
を配置します。
cd /home/isucon git clone https://github.com/isucon/isucon9-qualify.git
初期データを用意
make を実行します。docker を使って初期データを作成します。
cd /home/isucon/isucon9-qualify/initial-data/ make
生成された initial.sql は、/home/isucon/isucari/webapp/sql/initial.sql
とは異なるデータになっているので同期させます。
cp /home/isucon/isucon9-qualify/initial-data/result/initial.sql /home/isucon/isucari/webapp/sql/initial.sql
ベンチマーク用画像データをダウンロード
cd /home/isucon/isucon9-qualify/initial-data/ curl -L -O "https://github.com/isucon/isucon9-qualify/releases/download/v2/bench1.zip" unzip bench1.zip rm -rf images mv v3_bench1 images
ベンチマーカーを make (bin/benchmarker)
cd /home/isucon/isucon9-qualify/ make
動作確認をします。最後に以下のような出力がされていれば OK です。
./bin/benchmarker <省略> 2019/09/15 01:04:20 main.go:180: === final check === 2019/09/15 01:04:20 main.go:212: 2110 0 {"pass":true,"score":2110,"campaign":0,"language":"Go","messages":[]}
あとそれから
今回の isucon で私がボトルネックを検出するために作った計測ツールを先日 npm publish
しました。
使い方
cd /home/isucon/isucari/webapp/nodejs npm install performance-measure
edit /home/isucon/isucari/webapp/nodejs/index.ts
diff --git a/index.ts b/index.ts index f8a6ca6..d769f00 100755 --- a/index.ts +++ b/index.ts @@ -15,6 +15,9 @@ import crypt from "crypto"; import bcrypt from "bcrypt"; import {paymentToken, shipmentCreate, shipmentRequest, shipmentStatus} from "./api"; +const PerformanceMeasure = require('performance-measure') +const m = new PerformanceMeasure() + const execFile = util.promisify(childProcess.execFile); type MySQLResultRows = Array<any> & { insertId: number }; @@ -251,21 +254,42 @@ async function getDBConnection() { return fastify.mysql.getConnection(); } +// measure +fastify.addHook('preHandler', function (request :any, reply: any, next) { + m.start(request.raw.id) + next() +}) + +fastify.addHook('onSend', function (request: any, reply: any, _, next) { + const routeId = reply.context.config.statsId ? reply.context.config.statsId : request.raw.url + m.endAs(request.raw.id, routeId) + next() +}) + +fastify.get('/__stats__', async (req, reply) => { + const style = "font-family: 'Fira Mono', 'Andale Mono', 'Consolas', 'monospace';" + reply + .header('Content-Type', 'Content-type: text/html; charset=utf-8') + .send(`<pre style="${style}">${m.print()}</pre>`) +}) + +function c (statsId: string) { + return { config: { statsId } } +} // API fastify.post("/initialize", postInitialize); -fastify.get("/new_items.json", getNewItems); -fastify.get("/new_items/:root_category_id(^\\d+).json", getNewCategoryItems); -fastify.get("/users/transactions.json", getTransactions); -fastify.get("/users/:user_id(^\\d+).json", getUserItems); -fastify.get("/items/:item_id(^\\d+).json", getItem); +fastify.get("/new_items.json", c("/new_items.json"), getNewItems); +fastify.get("/new_items/:root_category_id(^\\d+).json", c("/new_items/:root_category_id(^\\d+).json"), getNewCategoryItems); +fastify.get("/users/transactions.json", c("/users/transactions.json"), getTransactions); +fastify.get("/users/:user_id(^\\d+).json", c("/users/:user_id(^\\d+).json"), getUserItems); +fastify.get("/items/:item_id(^\\d+).json", c("/items/:item_id(^\\d+).json"), getItem); fastify.post("/items/edit", postItemEdit); fastify.post("/buy", postBuy); fastify.post("/sell", postSell); fastify.post("/ship", postShip) fastify.post("/ship_done", postShipDone); fastify.post("/complete", postComplete); -fastify.get("/transactions/:transaction_evidence_id(^\\d+).png", getQRCode); +fastify.get("/transactions/:transaction_evidence_id(^\\d+).png", c("/transactions/:transaction_evidence_id(^\\d+).png"), getQRCode); fastify.post("/bump", postBump); fastify.get("/settings", getSettings); fastify.post("/login", postLogin); @@ -277,10 +301,10 @@ fastify.get("/", getIndex); fastify.get("/login", getIndex); fastify.get("/register", getIndex); fastify.get("/timeline", getIndex); -fastify.get("/categories/:category_id/items", getIndex); +fastify.get("/categories/:category_id/items", c("/categories/:category_id/items"), getIndex); fastify.get("/sell", getIndex); -fastify.get("/items/:item_id/edit", getIndex); -fastify.get("/items/:item_id/buy", getIndex); +fastify.get("/items/:item_id/edit", c("/items/:item_id/edit"), getIndex); +fastify.get("/items/:item_id/buy", c("/items/:item_id/buy"), getIndex); fastify.get("/buy/complete", getIndex); async function getIndex(_req: any, reply: FastifyReply<ServerResponse>) { @@ -309,7 +333,7 @@ async function postInitialize(req: FastifyRequest, reply: FastifyReply<ServerRes const res = { // キャンペーン実施時には還元率の設定を返す。詳しくはマニュアルを参照のこと。 - campaign: 0, + campaign: 2, // 実装言語を返す language: "nodejs", };
node.js を起動
systemctl stop isucari.golang.service systemctl disable isucari.golang.service systemctl start isucari.nodejs.service systemctl enable isucari.nodejs.service
ベンチ実行
2019/09/15 02:16:57 main.go:180: === final check === 2019/09/15 02:16:58 main.go:212: 5410 0
GET https://isucon9.catatsuy.org/__stats__
name size sum max min mean ------------------------------------------------ ---- ---------- ------- ------- ------- /buy 529 1379186.94 3843.30 0.03 2607.16 /items/:item_id(^\d+).json 1066 802732.08 3839.38 1.30 753.03 /login 704 782362.84 4105.26 225.83 1111.31 /settings 666 545591.99 3765.35 4.80 819.21 /new_items/:root_category_id(^\d+).json 366 383428.45 4208.59 162.25 1047.62 /new_items.json 126 145147.42 4250.52 217.48 1151.96 /users/transactions.json 50 111228.35 7035.00 45.94 2224.57 /users/:user_id(^\d+).json 119 97799.55 3978.04 47.27 821.84 /sell 40 24101.81 1527.11 0.03 602.55 /ship 10 8616.09 2033.46 0.38 861.61 /complete 8 8140.25 2017.89 9.76 1017.53 /ship_done 11 7456.80 1591.32 0.03 677.89 /initialize 1 6554.08 6554.08 6554.08 6554.08 /bump 7 3852.41 1223.84 15.66 550.34 /transactions/:transaction_evidence_id(^\d+).png 10 3465.90 1067.22 0.85 346.59 /items/edit 4 1496.02 1064.49 3.50 374.01 /reports.json 1 477.86 477.86 477.86 477.86 /static/js/2.ff6e1067.chunk.js 1 244.51 244.51 244.51 244.51 /upload/30f7679c97b5bb567dc1b38e3f52601a.jpg 2 22.00 21.72 0.27 11.00 /upload/0674e4389f096c8afd8b114b89275de6.jpg 1 21.18 21.18 21.18 21.18 /upload/5e8f91b52cb52c6b8d72533cab6f63b7.jpg 1 19.60 19.60 19.60 19.60 /upload/0d14fcbed9720312fafb8573d8556f51.jpg 1 13.33 13.33 13.33 13.33 /upload/1a571465c3b144d02490e3115208f8ca.jpg 1 11.76 11.76 11.76 11.76 /upload/30325ba77825014e96d42b19c18b9ee4.jpg 1 7.67 7.67 7.67 7.67 /static/js/runtime~main.a8a9905a.js 1 7.46 7.46 7.46 7.46 /upload/9b2bb8fb771e26dfbf335798f2adbd7a.jpg 1 3.50 3.50 3.50 3.50 /upload/62da8c459ff224e10f297a8deb207349.jpg 1 2.53 2.53 2.53 2.53 /upload/17aba6bc9657f59ba91ec376d08c3255.jpg 1 2.52 2.52 2.52 2.52 /upload/2dd7e13de6eadfc195a94c9c4d34884c.jpg 1 2.51 2.51 2.51 2.51 /upload/393afbdea5b3308247015ad89db679d9.jpg 1 1.97 1.97 1.97 1.97 /upload/26e8c534dca0c993c4fd0581c8a75a20.jpg 1 1.95 1.95 1.95 1.95 /upload/2efc92a5d55e12337d8f50d80ee0cf0b.jpg 1 1.95 1.95 1.95 1.95 /upload/2e0ba97d1012991aae5f83a447105342.jpg 1 1.95 1.95 1.95 1.95 /upload/5f57c8f5f424d3187a5097e5bc349cbc.jpg 1 1.86 1.86 1.86 1.86 /upload/30f113dd78473b35e8b3df60bc1dc7bd.jpg 1 1.86 1.86 1.86 1.86 /upload/7c6b3916fe91112d88d9f810b745aae5.jpg 1 1.72 1.72 1.72 1.72 /upload/169534d0a6d9d37be61d4737bfcd0a81.jpg 1 1.54 1.54 1.54 1.54 /upload/30eacdcf0bd8b425ce8112845974d8be.jpg 1 1.31 1.31 1.31 1.31 /upload/3a47c2abbaa28eeb79b322033b56c175.jpg 1 1.18 1.18 1.18 1.18 /upload/2f233413a51dfd3983f0e9feba54bcb5.jpg 1 1.15 1.15 1.15 1.15 /upload/3104fe69b6596368bb86db005c17b3f1.jpg 1 1.11 1.11 1.11 1.11 /upload/2e88083aaaa21439d3cb8520ad38d8fd.jpg 1 1.11 1.11 1.11 1.11 /upload/40c71b0281e1cbff0b8e2c71e355b6e0.jpg 1 1.08 1.08 1.08 1.08 /upload/30935566cc5c445de0920cdb12950a17.jpg 1 1.02 1.02 1.02 1.02 /upload/3fd4a90b3c3f80755468aac1292d1d3f.jpg 1 1.00 1.00 1.00 1.00 /upload/2ccfaf5b7ace96f26e9ba26a7002c4ad.jpg 1 0.90 0.90 0.90 0.90 /static/js/main.babc3d4d.chunk.js 1 0.88 0.88 0.88 0.88 /upload/47f8232fc19e4a8034b8580eb6a69ada.jpg 1 0.82 0.82 0.82 0.82 /upload/17892821abdb57d7e8cf05e750f1b063.jpg 1 0.79 0.79 0.79 0.79 /upload/3118b492c1b976decd88bf3c71cd7813.jpg 1 0.77 0.77 0.77 0.77 /static/css/main.19393e92.chunk.css 1 0.69 0.69 0.69 0.69 /upload/30e884e88d49d8c6979f30cf89c5954e.jpg 1 0.63 0.63 0.63 0.63 /upload/30cb5e2438a8d2d31b5cc388a2ec665b.jpg 1 0.62 0.62 0.62 0.62 /upload/270e6b5b8bd15f200f54d617449a8150.jpg 1 0.60 0.60 0.60 0.60 /upload/15fb39a6cd94ce77f8903879aecc7945.jpg 1 0.59 0.59 0.59 0.59 /upload/2e7c0c29569c8bfe80c9b46367db87b2.jpg 1 0.56 0.56 0.56 0.56 /upload/03024b6a442d9932fc55919b1a6dbcab.jpg 1 0.54 0.54 0.54 0.54 /upload/30d141435d573e446a935b8ebe4c0270.jpg 1 0.47 0.47 0.47 0.47 /upload/30e64ab77ec09bb3b083d22dae89a203.jpg 1 0.46 0.46 0.46 0.46 /upload/30333707b92970cad1817c46c0726049.jpg 1 0.44 0.44 0.44 0.44 /upload/237058d87bb27255efcda80870d5af5b.jpg 1 0.41 0.41 0.41 0.41 /upload/30480d069d071b8a7beff3a6529b7a5b.jpg 1 0.40 0.40 0.40 0.40 /upload/534c5fffb5cd56f903caa807ea8af714.jpg 1 0.38 0.38 0.38 0.38 /upload/3d9e29dc8f9a8af8913e83e317f2cfd1.jpg 1 0.36 0.36 0.36 0.36 /upload/301712d7770ac99623d90a88cc2c663c.jpg 1 0.35 0.35 0.35 0.35 /upload/41ddf24e267a66474d01afaff368f046.jpg 1 0.35 0.35 0.35 0.35 /upload/30471846202de60d114ee201c3ef3166.jpg 1 0.34 0.34 0.34 0.34 /upload/2f8454793d91d4a17a8932474d50dd92.jpg 1 0.34 0.34 0.34 0.34 /upload/0e480baa07ce38a1a10a34909460e5f6.jpg 1 0.33 0.33 0.33 0.33 /upload/302815cd68966575618cb9ccc4afafc6.jpg 1 0.33 0.33 0.33 0.33 /upload/30c480dfca6870d6a6b710189e162861.jpg 1 0.31 0.31 0.31 0.31 /upload/30c6ae135ad2a68517f2baf58bb9d7fa.jpg 1 0.29 0.29 0.29 0.29
こちらからは以上です。
追記
運営側へのお礼を言い忘れてました。今年も楽しく参加させて頂きました。毎年こんなに効率よくエンジニアとしての力量が向上するイベントを開催して頂いて感謝しております。次回も開催して欲しいといつも思っています。これだけの規模のイベントをハンドリングできる強いチームは他に存在していないと思うので継続してもらえるとありがたいです。今年も運営のみなさまお疲れさまでした。