ISUCON5ã®äºé¸ã«åå ãã¦ãå§åçãªå·®ã§è² ããã®ã§ã ãã®æãããããã«å¾©ç¿ãã¦ãèªåã®åã«ãããã¨æãã
ä»åã®ãã¡ã¤ãã§ã¯ã¢ããªã®ä¿®æ£ãç¹ã«éè¦ã§ãã£ãããã«æãã
ããã§ã¢ããªã®ä¿®æ£ã«ç¦ç¹ãå½ã¦ã¦ããããããã°ããã£ããã追ã£ã¦ãããèªåã®ãã®ã¨ãã¦ç¿å¾ãããã
ã¨ã¯ãããæ¬çªã¨ã¾ã£ããåãç¶æ³ãä½ããã¨ã¯ã§ããªãã®ã§ããã¼ã«ã«ç°å¢ã§ãã³ããã¼ã¯ãèµ°ããã¦ãç°¡æã«å¾ç¹ãè¦ã¦ãããã¨ã«ããã
ISUCON5ã®äºé¸ã§ä½¿ãããã¢ããªã®ã³ã¼ãã¨ãã³ããã¼ã¯ã®ã³ã¼ããgceç¨ã®ã¤ã¡ã¼ã¸ã¯ãã§ã«å ¬éããã¦ããã®ã§ãã¡ãã使ãã
ãªãã極åã¢ããªã®ä¿®æ£ã«éä¸ãããããnginx.confãmy.cnfã¯ããããªããunicornã®workeræ°ããããããªãã ã¤ã³ãã©ã¯ãããããã¼ãã«ã«ã¤ã³ããã¯ã¹ãè²¼ãç¨åº¦ã¨ããã
ããã¯ãISUCONäºé¸æ¬çªã§ããããã¤ã³ãã©ã«æéãããã¦ã¢ããªã®ä¿®æ£ãæ ã£ãèªåã¸ã®æãã§ããã
ãªããå ¨ä½æ¥ã³ã¼ãã¯ãã¡ãã§å ¬éãã¦ããã
ç°å¢æºå
ã¾ãã¯databaseãdumpãã¦ãã¼ã«ã«ç°å¢ãç¨æããã
gcpã§SSDã®ã¤ã³ã¹ã¿ã³ã¹ãé¸ãã§mysqldumpãå®è¡ããããã®ã¨ããgzipå§ç¸®ãè¡ããã¨ã§ããã£ã¹ã¯I/Oãæ¸ããã
mysqldump isucon5q | gzip > isucon5q.sql.gz
ç£æ°ãã£ã¹ã¯ã§gzipãªãã§å®è¡ããã¨ã30å以ä¸ããã£ã¦ãã¾ãããSSD+gzipã ã¨3åã»ã©ã§çµããã
ããããã¼ã«ã«ã«ã³ãã¼ãã¦databaseãä½ã£ã¦ããã
mysql -u root -e 'create database isucon5q' mysql -u root isucon5q < isucon5q.sql
ããã§ã¢ããªãåãããã¨ãã§ããããã«ãªã£ãã ãªããã¢ããªã®è¨èªã¯Rubyã¨ããã
ãã³ããã¼ã¯
ãã£ããã¢ããªãç«ã¡ä¸ãã¦ã¿ã¦ããä½ãããã«ããã¯ãªã®ãããããªãã
unicornã®ãã°ãè¨å®ãã¦ãã¬ã¹ãã³ã¹ã¿ã¤ã ãè¨é²ãã¦ããããã³ããã¼ã¯ãèµ°ããã¦ã¿ãã
https://github.com/ksss/isucon5q-fukusyu/commit/6534e5d614e7dfb73f72388ef3ce4270eb66ab58
ãã³ããã¼ã¯ã®ãã«ãã¯ãããã¥ã¡ã³ãéãã«ããã°ã§ããã
ã¢ããªå´
RACK_ENV=deployment bundle ex unicorn -c unicorn_config.rb
ãã³ããã¼ã¯å´(isucon/isucon5-qualify/bench)
$ jq '.[0]' < ../webapp/script/testsets/testsets.json | gradle run -Pargs="net.isucon.isucon5q.bench.scenario.Isucon5Qualification localhost:8080"
çµæ
{ "valid" : true, "requests" : 503, "elapsed" : 65528, "done" : "[{Isucon5InitExecutor},{BootstrapChecker},{Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Checker}]", "responses" : { "success" : 367, "redirect" : 135, "failure" : 1, "error" : 0, "exception" : 0 }, "violations" : [ ] }
successã¯1ç¹ãredirectã¯0.1ç¹ãªã®ã§ãåæã¹ã³ã¢ã¯å¤§ä½370ç¹ãããã ã
ãã®ç¹æ°ã¯ããã¾ã§ãã¼ã«ã«ç°å¢ã§ã®å®è¡çµæãªã®ã§ããã£ã¹ã¯ã¯SSDã ããCPUã8 coreã ã
ãªã®ã§ãããããã®æ¯è¼ã¨ãã¦è¦ã¦æ¬²ããã
ãã³ããã¼ã¯ã®çµæãè¦ã¦ã¿ãã
ãããã便å©ãã¼ã«ã¯ããã¿ããã ãã©ãã¨ãããã以ä¸ã§ãã ãããåããã
$ awk '{print $11 " - - " $7}' < unicorn.log | sort -n | tail 0.6953 - - / 0.6960 - - / 0.6987 - - / 0.7006 - - / 0.7077 - - / 0.7130 - - / 0.7184 - - / 0.7193 - - / 0.7223 - - / 0.7265 - - /
ãªãã»ã©ãã¨ã«ãã/
ãé
ãããã ã
ãªããä»å¾ãåææ³ã§ãã³ããã¼ã¯ãèµ°ãããã
SQLãã°ãåºã
ã¢ããªã®ããã«ããã¯ã¯å¤§ä½SQLã ããã¨æ±ºãã¤ãã ã©ããªSQLãåºã¦ããã®ãç¥ãããã¨ããã
ããããªããmysql.cnfããããã®ã¯ããã©ãããããã¯ããé ã«ä¸¦ã¹ãããä½æ¬ã®SQLãæµãã¦ããã®ãæ°ããããããã
ããã§ãmysql2-clientã¢ã³ãã¼ããããä½ã£ãã
æå®ãããSQLãbacktraceãå®è¡æéãè¨é²ãã¦ããã¦ãããããããafter
ããã¯ã¸å°å
¥ããã
https://github.com/ksss/isucon5q-fukusyu/commit/240e4c9f702a28dcb15e680dc6f527a2c7b1e934
ãã°ã«ã¯ããåºã¦ããã
... SELECT * FROM relations WHERE one = '3657' OR another = '3657' ORDER BY created_at DESC; 0.124001s path:/ sql:1232 0.435481s 127.0.0.1 - - [12/Oct/2015:15:51:53 +0900] "GET / HTTP/1.1" 200 16637 0.7254
ãªãã»ã©ãå ¨ä½ã§ã¯0.72sãSQLã ãã ã¨0.44sã1232æ¬ã®SQLãä¸çªé ãSQLã¾ã§ããã£ãã
åéãã§ãã¯ãæ¹å
ä¸çªé ãSQLã¯èªåã®åã ã¡å ¨ã¦ãã¨ã£ã¦ããé¨åã ãã1232æ¬ã®SQLãã¡ãã»ã¨ãã©ãrelationsã¸ã®SELECTã ã£ãã ä¸ã¤ä¸ã¤ã¯0.0002sç¨åº¦ã ããããã1000æ¬ããã°0.2sã«ãªãã æé SQLãå«ãã¦ãSQLåå¾ã«ãããã»ã¨ãã©relationsã«ããã£ã¦ããããã ã£ãã ãã®relationsãæ¹åããã°ãé«éåãæå¾ ã§ãããã ã
åé¡ã®SQLãåãã¦ããé¨åã¯is_friend?
ã¨ãããèªåã¨ç¸æãåéãã©ãã調ã¹ãé¨åã ãmysql2-client-general_logã§ã¯backtraceããããã§ããã®ã§ãSQLã®çºçå ´æã容æã«ç¹å®ã§ããã
ã³ã¼ããèªãã¨ããªãã»ã©ãentriesã1000件ã¨ã£ã¦ãã¦åéãããªããã®ãå¼¾ãé¨åã¨ãcommentsã1000件ã¨ã£ã¦ãã¦åéãããªããã®ãå¼¾ãé¨åããããããã ã
https://github.com/ksss/isucon5q-fukusyu/blob/240e4c9f702a28dcb15e680dc6f527a2c7b1e934/app.rb#L189 https://github.com/ksss/isucon5q-fukusyu/blob/240e4c9f702a28dcb15e680dc6f527a2c7b1e934/app.rb#L197
ã¨ãããã§å®æã«JOINããã°ãããããã¨åãçµãã¨ãORãå«ãã é£ããSQLã«æ©ã¾ããã¦æéåãã«ãªã£ãåéã®ãã¼ã ã®äºã®èãã ã
ææ¥ã¸ã®æè¨: è½ã¡çããã¾ãããã¿ããã³ã¡ã³ããã¤ãã¾ãã£ã¦ããããã³ã¼ããèªã
ããå°ãè½ã¡çãã¦å¨ããè¦ã¦ããã¨ãæ°ã«ãªãã¨ããã2ã¤è¦ãã¦ããã
åéä¸è¦§ã¯ãã¨ã§åå¾ãã¦ããã¨ããhttps://github.com/ksss/isucon5q-fukusyu/blob/240e4c9f702a28dcb15e680dc6f527a2c7b1e934/app.rb#L205-L211ã¨ã åéã追å ãã¦ããã¨ããhttps://github.com/ksss/isucon5q-fukusyu/blob/240e4c9f702a28dcb15e680dc6f527a2c7b1e934/app.rb#L361ã ã
åéä¸è¦§ãã¨ã£ã¦ãããªããããããSQLãã¤ãã£ã¦åéãã©ãã調ã¹ãå¿
è¦ã¯ãªãã
ã¾ããåéã追å ãã¦ããã¨ããã§ã¯ãone
another
ã«äº¤äºã«èªåã¨ç¸æã追å ããä»æ§ã«ãªã£ã¦ãããã¨ãåãããã¤ã¾ãã¯èªåã®åã ã¡ã調ã¹ãã ããªãone
ã ããè¦ãã°ããã
ãªãããã³ããã¼ã«ã¼ãã©ãã¾ã§è¦ã¦ããã®ãããããªã以ä¸ã表示ããããã¼ã¿ãå¤ãã£ã¦ã¯ãããªãã ãããã表示ããããã¼ã¿ãå¤ãã£ããã©ãããç¥ããã¹ããªãã
ããã¯ç°¡æã«ãåºåãããHTMLãæ¯è¼ããã¨ããæ³¥èãæãã§ãã£ã¦ã¿ãã
ãã ãããã³ããã¼ã¯ãåæå¤ãæ´æ°ãã¦ãã¾ããããªã®ã§ããã³ããã¼ã¯ãèµ°ããã度ã«HTMLãæ´æ°ããªããã°ãããªãã®ãé£ç¹ã
ãã°ã¤ã³ããã¢ã«ã¦ã³ãã決ãæã£ã¦ããã©ã¦ã¶ã®ã³ã³ã½ã¼ã«ããHTMLããã¡ã¤ã«ã«ã³ãããããã¨ã§æ¯è¼ç¨ã®ãã¼ã¿ãä½ã£ã¦ããã
ããã¹ãã®diffãè¦ãã®ã«ã¯ãdiffyã¨ããgemã便å©ã ã£ãã
https://github.com/ksss/isucon5q-fukusyu/commit/ef65e442e0eedbcc3bb9f42f67a5d57e60697bea
ææ¥ã¸ã®æè¨: ä¸å®ã¯ç©ã¿éãªããæ£å¸¸ãªå¤æãã§ããªããªããå´©å£ãããä¸å®ãªããã¹ãããã
ããã§ãããããã£ã¦ããhtmlãå¤ãã£ããæ¤ç¥ã§ããããã«ãªã£ãã
åéä¸è¦§æ å ±ãã以éã§ãæµç¨ããããã«æ¹åãã¦ã¿ãã
https://github.com/ksss/isucon5q-fukusyu/commit/26d46912fb5c6ecbf0db81edb61a325e4481ea7e
ããã§ãã°ã¯ãããå¤åããã
- SELECT * FROM relations WHERE one = '3657' OR another = '3657' ORDER BY created_at DESC; 0.124001s - path:/ sql:1232 0.435481s - 127.0.0.1 - - [12/Oct/2015:15:51:53 +0900] "GET / HTTP/1.1" 200 16637 0.7254 + SELECT * FROM relations WHERE one = '3657' OR another = '3657' ORDER BY created_at DESC; 0.132749s + path:/ sql:82 0.263436s + 127.0.0.1 - - [12/Oct/2015:17:14:59 +0900] "GET / HTTP/1.1" 200 16637 0.4542
æé SQLã¯å¤ããããSQLã®æ¬æ°ã¯1232->82ã¨æ¿æ¸ãSQLæéããç®è«è¦éãç´0.17sæ¸ããã¼ã¿ã«æéãSQLçºè¡æ¯ã«ããªãã¸ã§ã¯ãåãªã©ã®ãªã¼ãã¼ããããããã®ã§ãããã0.17sãããããã«0.1så¤ãã0.27sæ¸ã¨ãªã£ãã
ãã³ããã¼ã¯ã¹ã³ã¢ã¯
{ "valid" : true, "requests" : 712, "elapsed" : 67053, "done" : "[{Isucon5InitExecutor},{BootstrapChecker},{Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Checker}]", "responses" : { "success" : 533, "redirect" : 178, "failure" : 1, "error" : 0, "exception" : 0 }, "violations" : [ ] }
550ç¹ã¨ãã£ãã¨ããã+180ç¹ã«ãªã£ãã
$ awk '{print $11 " - - " $7}' < unicorn.log | sort -n | tail 0.4582 - - / 0.4623 - - / 0.4657 - - / 0.4686 - - / 0.4696 - - / 0.4743 - - / 0.4748 - - / 0.4806 - - / 0.4920 - - / 0.5393 - - /
ãã°ã¯ãã®éãããã¯ãã/
ãé
ãã®ã§ãå¼ãç¶ã/
ãæ¹åãã¦ããã
åéä¸è¦§ãæ¹å
ãã£ã¨ãé ãSQLã¯ä»¥ä¸ã®ã¨ããã§ã0.13sãããã£ã¦ããã
SELECT * FROM relations WHERE one = '3657' OR another = '3657' ORDER BY created_at DESC;
EXPLAINãã¦ã¿ãã
$ mysql -u root isucon5q -e 'EXPLAIN SELECT * FROM relations WHERE one = '3657' OR another = '3657' ORDER BY created_at DESC;' +----+-------------+-----------+------+---------------+------+---------+------+--------+-----------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-----------+------+---------------+------+---------+------+--------+-----------------------------+ | 1 | SIMPLE | relations | ALL | friendship | NULL | NULL | NULL | 494134 | Using where; Using filesort | +----+-------------+-----------+------+---------------+------+---------+------+--------+-----------------------------+
ã©ãã¿ã¦ããã«ã¹ãã£ã³ã ã
åéä¸è¦§ããone
ã ãã®æ¤ç´¢ã«ãã¦ãone
ã«ã¤ã³ããã¯ã¹ãè²¼ã£ã¦ã¿ãã
https://github.com/ksss/isucon5q-fukusyu/commit/4995395b8b586f905093fa39732f7afc027242cd
mysql -u root isucon5q -e 'alter table relations add index one(one);'
ãã°ã¯ãããªã£ãã
- SELECT * FROM relations WHERE one = '3657' OR another = '3657' ORDER BY created_at DESC; 0.132749s - path:/ sql:82 0.263436s - 127.0.0.1 - - [12/Oct/2015:17:14:59 +0900] "GET / HTTP/1.1" 200 16637 0.4542 + SELECT user_id, owner_id, DATE(created_at) AS date, MAX(created_at) AS updated + FROM footprints + WHERE user_id = '3657' + GROUP BY user_id, owner_id, DATE(created_at) + ORDER BY updated DESC + LIMIT 10 + ; 0.099964s + path:/ sql:82 0.132781s + 127.0.0.1 - - [12/Oct/2015:19:40:15 +0900] "GET / HTTP/1.1" 200 16638 0.3112
ä¸çªé ãSQLãåéä¸è¦§ã®åå¾ããããããã¨ä¸è¦§ã®åå¾ã«å¤ããã0.13sãã0.10sã«å¤åããã SQLéã¯å¤ãããªãããæéã¯ç´ååã«ãªã£ã¦ããã å ¨ä½ã§ã¯0.14sç縮ã§ããããã ã
ãã³ããã¼ã¯çµæã¯
{ "valid" : true, "requests" : 882, "elapsed" : 64103, "done" : "[{Isucon5InitExecutor},{BootstrapChecker},{Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Checker}]", "responses" : { "success" : 672, "redirect" : 209, "failure" : 1, "error" : 0, "exception" : 0 }, "violations" : [ ] }
ç´690ç¹ã+140ç¹ã¨ãªã£ãã
é
ãã¢ã¯ã»ã¹ãã¹ã¯ãã¯ã/
ãªããã ã
$ awk '{print $11 " - - " $7}' < unicorn.log | sort -n | tail 0.3342 - - / 0.3411 - - / 0.3413 - - / 0.3459 - - / 0.3509 - - / 0.3528 - - / 0.3616 - - / 0.3667 - - / 0.3941 - - / 0.4094 - - /
ãããã¨èª¿æ´
ååå¤åããæé ã®SQLãEXPLAINã§è¦ã¦ã¿ãã
$ mysql -u root isucon5q -e 'EXPLAIN SELECT user_id, owner_id, DATE(created_at) AS date, MAX(created_at) AS updated FROM footprints WHERE user_id = '3657' GROUP BY user_id, owner_id, DATE(created_at) ORDER BY updated DESC LIMIT 10;' +----+-------------+------------+------+---------------+------+---------+------+--------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+------+---------------+------+---------+------+--------+----------------------------------------------+ | 1 | SIMPLE | footprints | ALL | NULL | NULL | NULL | NULL | 499597 | Using where; Using temporary; Using filesort | +----+-------------+------------+------+---------------+------+---------+------+--------+----------------------------------------------+
ãã«ã¹ãã£ã³ã®ããã ã ãªãã人ãªãSQLãã¿ãã°indexã®è²¼ãã©ãããããã£ã¦ããããä»åã®ISUCONã§ã¯ç£æ°ãã£ã¹ã¯ã®é ãã«æ©ã¾ãããããã¿ã«indexãã¯ã£ã¦ããã¨ä½æ¥æéã®ãã¹ã«ãªã£ã¦ããã*1 ããã¯æå°éã®ä½æ¥ã ããè¡ãã
mysql -u root isucon5q -e 'alter table footprints add index user_id(user_id);'
ããã§ãã°ã¯ããå¤åããã
- SELECT user_id, owner_id, DATE(created_at) AS date, MAX(created_at) AS updated - FROM footprints - WHERE user_id = '3657' - GROUP BY user_id, owner_id, DATE(created_at) - ORDER BY updated DESC - LIMIT 10 - ; 0.099964s - path:/ sql:82 0.132781s - 127.0.0.1 - - [12/Oct/2015:19:40:15 +0900] "GET / HTTP/1.1" 200 16638 0.3112 + SELECT * FROM entries ORDER BY created_at DESC LIMIT 1000; 0.011207s + path:/ sql:82 0.030177s + 127.0.0.1 - - [12/Oct/2015:22:51:01 +0900] "GET / HTTP/1.1" 200 16637 0.2122
æé SQLãå¤åãã0.133sãã0.011sã«ã¾ã§ã«ãªã£ãã SQLéã¯ã¤ã³ããã¯ã¹ãå¼µã£ãã ããªã®ã§å½ç¶å¤åããããããSQLæéã¯0.1sç縮ããã¦ããã ãã¼ã¿ã«ã0.1sæ¸ã«ãªã£ãã
ãã³ããã¼ã¯ã¯ç´1070ç¹ã+380ç¹ã¨ãªã£ãã
{ "valid" : true, "requests" : 1361, "elapsed" : 63577, "done" : "[{Isucon5InitExecutor},{BootstrapChecker},{Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Checker}]", "responses" : { "success" : 1049, "redirect" : 311, "failure" : 1, "error" : 0, "exception" : 0 }, "violations" : [ ] }
é
ãã®ã¯ãã¯ã/
ã§ããã®ã¯å¤ãããªãããã ã
$ awk '{print $11 " - - " $7}' < unicorn.log | sort -n | tail 0.2187 - - / 0.2190 - - / 0.2198 - - / 0.2207 - - / 0.2209 - - / 0.2214 - - / 0.2230 - - / 0.2238 - - / 0.2323 - - / 0.2514 - - /
ã¤ã³ããã¯ã¹ãçµãã£ããï¼
ããã¾ã§ã¯æé ã®SQLãã¿ã¦indexãã¯ã£ã¦ã§ã¹ã³ã¢ã稼ãã§ãããã次ã®æé SQLã¯ã©ãã¿ã¦ãindexã§æ¹åãããããªãã
åºç¤ã¯ãããªæãã§SQLã®æ¹åãè¦ã¦ããã°ããã£ããã ã¨æãã
åæ©çãªSQLã®ç¥èãããã°ã誰ã§ã解ãããããªåé¡ã ã£ããã³ã¼ãã大ããå¤æ´éã¯ãªãã
ãã®æç¹ã«ããèªåãã¡ã¯ãã©ãã¤ããªãã£ãã®ã§ããã¯ãè½ã¡çããã¨ããä¸çªã®èª²é¡ã ã£ãã¨æãã
ææ¥ã¸ã®èª²é¡: 大äºãªãã¨ã ããä½åã§ãè¨ãããã¡ã¤ãã
ããããã¯ä¸ç¤ã¨ãã¦ãåé¡ãé£ãããªã£ã¦ããã
ãããã¡ã¤ã«
ããããã§ãããã¡ã¤ã«ãåã£ã¦ã¿ãã
Rubyã ã¨stackprofãæåãªããã ã
https://github.com/ksss/isucon5q-fukusyu/commit/b87eba3162b858588b84e3e80c2de9c9ad73997e
ããã§ä½åº¦ãã¢ã¯ã»ã¹ãã¦ã¿ã¦ãããã¡ã¤ã«ãè¦ã¦ã¿ã
$ stackprof /tmp/stackprof/stackprof-wall-*.dump --file app.rb | less
ã©ãããã®è¾ºããéãããã ã
| 195 | entries_of_friends = [] 2344 (20.8%) / 2249 (20.0%) | 196 | db.query('SELECT * FROM entries ORDER BY created_at DESC LIMIT 1000').each do |entry| 30 (0.3%) / 30 (0.3%) | 197 | next unless friends_map.key?(entry[:user_id]) | 198 | entry[:title] = entry[:body].split(/\n/).first | 199 | entries_of_friends << entry 16 (0.1%) / 16 (0.1%) | 200 | break if entries_of_friends.size >= 10 | 201 | end | 202 | | 203 | comments_of_friends = [] 3441 (30.6%) / 2836 (25.2%) | 204 | db.query('SELECT * FROM comments ORDER BY created_at DESC LIMIT 1000').each do |comment| 94 (0.8%) / 94 (0.8%) | 205 | next unless friends_map.key?(comment[:user_id]) 373 (3.3%) / 60 (0.5%) | 206 | entry = db.xquery('SELECT * FROM entries WHERE id = ?', comment[:entry_id]).first | 207 | entry[:is_private] = (entry[:private] == 1) 71 (0.6%) / 7 (0.1%) | 208 | next if entry[:is_private] && !permitted?(entry[:user_id]) | 209 | comments_of_friends << comment 7 (0.1%) / 7 (0.1%) | 210 | break if comments_of_friends.size >= 10 | 211 | end
ããã¯æªã ã«ããããªãã¾ã¾ã®è¬ç¾è±¡ãªã®ã ããä¸è¨ã³ã¼ãã¯unicornä¸ã ã¨é ãã
Benchmark.realtime{ db.query('SELECT * FROM comments ORDER BY created_at DESC LIMIT 1000').each{ |c| } }
åç´ãªRackã¢ããªãä½ã£ã¦è¨æ¸¬ããã¨ããã
WEBrick 1.3.1ã§ã¯0.011241
ã
unicorn 4.9.0ã§ã¯0.108689
ã¨10åã»ã©å·®ããã£ãã
ãªãã ããããããã¨ã«ããé ãã
unicorn以å¤ã®é¸æè¢ãæã£ã¦ããã°ãããªãæ¤è¨¼ãã§ãããããããªãããããã¯SQLã工夫ãããã¨ã§åé¿ããã
ãcommentsã®ãã¼ã¿ãå¤ãã¦ãªãã¸ã§ã¯ãçæã«æéãããã£ã¦ããã®ããªï¼ãã¨äºæ³ãç«ã¦ãä¸è¨ã³ã¼ããè¨æ¸¬ãã¦ã¿ãã
commentsã®comment
ã¨created_at
ã«ã©ã ãã®ããããã®ã¨ãå
¨ã¦åå¾ããå ´åã ã
db.query('SELECT id, entry_id, user_id FROM comments ORDER BY created_at DESC LIMIT 1000').each{|c| } db.query('SELECT * FROM comments ORDER BY created_at DESC LIMIT 1000').each{|c| }
0.0032s 0.0106s
0.0035s 0.1061s
ãªãunicornãããã»ã©å·®ãã¤ãã®ãã¾ã£ããè¬ãªã®ã ããã¨ã«ããæ©ããªãããã ã
ããã¯æµç³ã«çµé¨åã¨ããããç¹å®ã®è¨èªã®ç¹å®ã®ã©ã¤ãã©ãªãçµã¿åãããã¨ãã®åä½ãªãã¦è¦ãã¦ãããªãã®ã§ãISUCONã¨ããå ´ã§æãã¤ãããã¨ããã¨ããªãå¾®å¦ã ã
comments.commentãããããã100æåè¡ããªãç¨åº¦ã®ãã¼ã¿ãªã®ã§ããã«ã©ã æ°Ãã¬ã³ã¼ãæ°ã§æéããããããããã®ãã¨ãè¦ããããç¡ããã
ãããã¡ã¤ã«ä¸ã¯ã0.21sã®30%ãªã®ã§ã0.063sãããããã£ã¦ããã¨ããããããä»ãã¦ãä¿®æ£ã«ãããããã¨å¤æãããããªãããã ã
é£ããããISUCONã
ææ¥ã¸ã®æè¨: ISUCONé£ãã
ããã§ã¯ãã®ç¾è±¡ãå©ç¨ãã¦ãåéãã§ãã¯ããprivateãã§ãã¯ãããçµããæ大10件ã ãã§å度SQLãæãã¦commentãåå¾ããããã«ã³ã¼ããæ¸ãæããã
https://github.com/ksss/isucon5q-fukusyu/commit/57de06712e3c5adb2d838296cc0a503d2cf5a1ed
- SELECT * FROM entries ORDER BY created_at DESC LIMIT 1000; 0.011207s - path:/ sql:82 0.030177s - 127.0.0.1 - - [12/Oct/2015:22:51:01 +0900] "GET / HTTP/1.1" 200 16637 0.2122 + SELECT * FROM entries ORDER BY created_at DESC LIMIT 1000; 0.012425s + path:/ sql:83 0.028977s + 127.0.0.1 - - [13/Oct/2015:10:20:44 +0900] "GET / HTTP/1.1" 200 16637 0.1352
SQLã1æ¬å¢ãããã®ã«ããããããããã¼ã¿ã«ã§0.08sæ¸ã«ãªã£ãã
ã¹ã³ã¢ã¯ç´1400ç¹ã+330ã«ãªã£ãã
{ "valid" : true, "requests" : 1774, "elapsed" : 63777, "done" : "[{Isucon5InitExecutor},{BootstrapChecker},{Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Checker}]", "responses" : { "success" : 1364, "redirect" : 409, "failure" : 1, "error" : 0, "exception" : 0 }, "violations" : [ ] }
/
ã®ä¸çªé
ãã£ãã¨ãã®é度æ¹åã¯ãã¾ãã¡ãï¼
$ awk '{print $11 " - - " $7}' < unicorn.log | sort -n | tail 0.2429 - - / 0.2431 - - / 0.2437 - - / 0.2577 - - / 0.2736 - - / 0.2760 - - / 0.2789 - - / 0.2848 - - / 0.2971 - - / 0.3371 - - /
ãããããã«ããã«ããã¯ããªããªã£ã¦ããã¨ããã¼ã¿éã«æ°ã使ãå¿ è¦ãããããã ã
ã¡ãªã¿ã«commentsã®user_idã«ã¤ã³ããã¯ã¹ãè²¼ã£ã¦ãfriend_map.keysã§æ¤ç´¢ãããã¨ã§ãã¼ã¿éãæããæ¹æ³ãããããããprivate対çãæãã¤ãããçµå±1000件ããæ¸ãããªãã£ãã ã¾ããentriesã¨JOINããã¨é常ã«é ããªã£ã¦ãã¾ããªã©ã§ãã以å¤ã®æ¹åãæãã¤ããªãã£ãã
ãã®ã¸ããç¿å¾ãã¦ããã©ã¼ãã³ã¹æ¹åã«ä½¿ããã¨ããã«ã¯ãçµé¨ã¨åãã¿ãããªã¨ããã®ç©ã¿éããªã®ããªãã
entriesæ¹å
| 195 | entries_of_friends = [] 1427 (63.6%) / 1400 (62.4%) | 196 | db.query('SELECT * FROM entries ORDER BY created_at DESC LIMIT 1000').each do |entry| 12 (0.5%) / 12 (0.5%) | 197 | next unless friends_map.key?(entry[:user_id]) | 198 | entry[:title] = entry[:body].split(/\n/).first | 199 | entries_of_friends << entry 7 (0.3%) / 7 (0.3%) | 200 | break if entries_of_friends.size >= 10 | 201 | end | 202 | | 203 | comments_of_friends = [] | 204 | comment_ids = [] 123 (5.5%) / 11 (0.5%) | 205 | db.query('SELECT id, entry_id, user_id FROM comments ORDER BY created_at DESC LIMIT 1000').each do |comment | 13 (0.6%) / 13 (0.6%) | 206 | next unless friends_map.key?(comment[:user_id]) 68 (3.0%) / 33 (1.5%) | 207 | entry = db.xquery('SELECT * FROM entries WHERE id = ?', comment[:entry_id]).first | 208 | entry[:is_private] = (entry[:private] == 1) 9 (0.4%) / 1 (0.0%) | 209 | next if entry[:is_private] && !permitted?(entry[:user_id]) | 210 | comment_ids << comment[:id] | 211 | break if comment_ids.length >= 10 | 212 | end 30 (1.3%) / 26 (1.2%) | 213 | db.xquery('SELECT * FROM comments WHERE id IN (?) ORDER BY created_at DESC LIMIT 10', comment_ids).each do |comment| | 214 | comments_of_friends << comment | 215 | break if comments_of_friends.size >= 10 | 216 | end
commentsã®æ¹åã«ãã£ã¦ãããã«ããã¯ãentriesã®åå¾ã«ãªã£ã¦ããããã ã
ãã®SQLã§ã¯entrieså ¨ä»¶ãcreated_até ã§ä¸¦ã¹æ¿ããä¸ãã1000件åã£ã¦ãããã ã
ããã®ä¸èº«ã¯commentsã»ã©è¤éã§ã¯ãªãã®ã§ãfriends_map.keys
ã§åéä¸è¦§ãWHERE INã§æ¤ç´¢ãã¦ãã¾ãã10件ã«çµãã
https://github.com/ksss/isucon5q-fukusyu/commit/3bad2014b299ad6b3281fdad3fd26e933c348038
- SELECT * FROM entries ORDER BY created_at DESC LIMIT 1000; 0.012425s - path:/ sql:83 0.028977s - 127.0.0.1 - - [13/Oct/2015:10:20:44 +0900] "GET / HTTP/1.1" 200 16637 0.1352 + SELECT user_id, owner_id, DATE(created_at) AS date, MAX(created_at) AS updated + FROM footprints + WHERE user_id = '3657' + GROUP BY user_id, owner_id, DATE(created_at) + ORDER BY updated DESC + LIMIT 10 + ; 0.002886s + path:/ sql:83 0.018291s + 127.0.0.1 - - [13/Oct/2015:17:31:10 +0900] "GET / HTTP/1.1" 200 16638 0.0498
ãã¼ã¿ã«ã§0.05sãããã«0.08sæ¸ã¨ãªã£ãã
ã¹ã³ã¢ã¯2280ç¹ã+880ç¹ã¨ããªãä¸æããã
{ "valid" : true, "requests" : 2872, "elapsed" : 63524, "done" : "[{Isucon5InitExecutor},{BootstrapChecker},{Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Load,Isucon5Checker}]", "responses" : { "success" : 2223, "redirect" : 648, "failure" : 1, "error" : 0, "exception" : 0 }, "violations" : [ ] }
é
ããã¹ã/
ã§ã¯ãªãã/friends
ã«ç§»è¡ã
$ awk '{print $11 " - - " $7}' < unicorn.log | sort -n | tail 0.1808 - - /friends 0.1808 - - /friends 0.1822 - - /friends 0.1852 - - /friends 0.1871 - - /friends 0.1872 - - /friends 0.1918 - - /friends 0.1924 - - /friends 0.2095 - - /friends 0.2468 - - /friends
ã§ã¯æ¬¡ã«/friends
ãæ¹åã¨è¡ãããã¨ããã ãããã以éãä¼¼ããããªæé ã§æ¹åãã¦ãããã ããã
SQLæ¹åãçµããã°ããå¾åæ¦ãããããã¯æªç¥ã®é åã ããããã¾ã§ã§ããªã復ç¿ã§ããããããªãã ãããã
è½ã¡çãã¦ããã«ããã¯ã«ä¸ã¤ã¥ã¤å¯¾å¦ãã¦ãããçµé¨ãç©ãã°ãããã«ããã¯ãå èªã¿ã§ãã¦ãåæ ä½æ¥ãã§ããã
ã¾ã¨ã
ISUCON5äºé¸ã®ãããããã°ããã£ãããæ¯ãè¿ã£ã¦ã¿ãã
2æ¬ã®alterã¨ããããªå®è£
ã®ä¿®æ£ã§/
ã¯/friends
ããã¯ãããªã£ãã
ãã¡ããååã«æéãããã¦æ¢ã£ã¦ãã£ãä¿®æ£ãªã®ã§ãæ¬çªã§ã¯éã«åããªãã£ãã ããã
次ã«ä¼¼ããããªãã¨ãèµ·ãã£ãã¨ãã対å¦ããããã¤ããå·éãã¨ãä»åã®å ããªçµé¨ããã¤ãå½¹ã«ç«ã¤æ¥ãæ¥ããããããªãã
æ¬ç·çªç ´å¢ã«ã¨ã£ã¦ã¯ããããããäºé¸åé¡ã®æ¬çªãã¨ãããããªå 容ã ã£ããããããªããã
ãã£ããã¨åºç¤ãè¦ãªããã¦ããå ã«é²ã¿ããã¨æãã
ææ¥ã¸ã®æè¨ãã¾ã¨ãã¦ã¿ããã
ä¸ã¤ è½ã¡çã
ä¸ã¤ ä¸å®ã¯ç©ã¿éãªããæ£å¸¸ãªå¤æãã§ããªããªããå´©å£ãããä¸å®ãªããã¹ãããã
ä¸ã¤ ã¨ã«ããè½ã¡çã
ä¸ã¤ ISUCONé£ã
è¯ãåé¡ããããã¨ããããã¾ããï¼ISUCONæé«ã§ããï¼
åèè³æ
åºé¡æ å½ã®kamipoããã«ãã解説ã é常ã«ããã«ãªãã®ã§ãä»åã®å¾©ç¿ã¨åããã¦ç¿å¾ãããã
ãã³ããã¼ã¯ã¯ç´¹ä»ããã¦ããã¨ããã«åãã¦ç´ æ´ãããã£ãã ãªã¢ã¼ããã·ã³ã«å¯¾ãã¦è¡ãã°ã社å ã§ISUCONã®å¾©ç¿ä¼ã¿ãããªãã¨ãã§ãããããããªãã
*1:SSDã¤ã³ã¹ã¿ã³ã¹ã§ã¤ã³ããã¯ã¹ã¯ã£ãã¤ã¡ã¼ã¸ã ãã¤ãã£ã¦ç£æ°ãã£ã¹ã¯ã¤ã³ã¹ã¿ã³ã¹ã«è¼ãæããã¨ããã¦ã«ãã©Cãå®è¡ãããã¼ã ãããããããã ããã