Closed pinkumohikan closed 1 month ago
$ /home/isucon/private_isu.git/benchmarker/bin/benchmarker -u /home/isucon/private_isu.git/benchmarker/userdata -t http://172.31.29.227
{"pass":true,"score":966,"success":843,"fail":0,"messages":[]}
total used free shared buff/cache available
Mem: 3.7Gi 1.0Gi 2.2Gi 2.9Mi 722Mi 2.7Gi
Swap: 0B 0B 0B
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ruby 682 isucon 7u IPv4 8321 0t0 TCP *:http-alt (LISTEN)
nginx 744 root 5u IPv4 6603 0t0 TCP *:http (LISTEN)
nginx 745 www-data 5u IPv4 6603 0t0 TCP *:http (LISTEN)
nginx 746 www-data 5u IPv4 6603 0t0 TCP *:http (LISTEN)
mysqld 1116 mysql 34u IPv4 8358 0t0 TCP localhost:mysql (LISTEN)
ruby 1119 isucon 7u IPv4 8321 0t0 TCP *:http-alt (LISTEN)
UNIT LOAD ACTIVE SUB DESCRIPTION
acpid.service loaded active running ACPI event daemon
apparmor.service loaded active exited Load AppArmor profiles
apport.service loaded active exited automatic crash report generation
blk-availability.service loaded active exited Availability of block devices
chrony.service loaded active running chrony, an NTP client/server
cloud-config.service loaded active exited Apply the settings specified in cloud-config
cloud-final.service loaded active exited Execute cloud user/final scripts
cloud-init-local.service loaded active exited Initial cloud-init job (pre-networking)
cloud-init.service loaded active exited Initial cloud-init job (metadata service crawler)
console-setup.service loaded active exited Set console font and keymap
cron.service loaded active running Regular background program processing daemon
dbus.service loaded active running D-Bus System Message Bus
finalrd.service loaded active exited Create final runtime dir for shutdown pivot root
fwupd.service loaded active running Firmware update daemon
getty@tty1.service loaded active running Getty on tty1
irqbalance.service loaded active running irqbalance daemon
isu-ruby.service loaded active running isu-ruby
keyboard-setup.service loaded active exited Set the console keyboard layout
kmod-static-nodes.service loaded active exited Create List of Static Device Nodes
lvm2-monitor.service loaded active exited Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
memcached.service loaded active running memcached daemon
ModemManager.service loaded active running Modem Manager
multipathd.service loaded active running Device-Mapper Multipath Device Controller
mysql.service loaded active running MySQL Community Server
networkd-dispatcher.service loaded active running Dispatcher daemon for systemd-networkd
nginx.service loaded active running A high performance web server and a reverse proxy server
plymouth-quit-wait.service loaded active exited Hold until boot process finishes up
plymouth-quit.service loaded active exited Terminate Plymouth Boot Screen
plymouth-read-write.service loaded active exited Tell Plymouth To Write Out Runtime Data
polkit.service loaded active running Authorization Manager
rsyslog.service loaded active running System Logging Service
serial-getty@ttyS0.service loaded active running Serial Getty on ttyS0
setvtrgb.service loaded active exited Set console scheme
snap.amazon-ssm-agent.amazon-ssm-agent.service loaded active running Service for snap application amazon-ssm-agent.amazon-ssm-agent
snapd.apparmor.service loaded active exited Load AppArmor profiles managed internally by snapd
snapd.seeded.service loaded active exited Wait until snapd is fully seeded
snapd.service loaded active running Snap Daemon
ssh.service loaded active running OpenBSD Secure Shell server
sysstat.service loaded active exited Resets System Activity Logs
systemd-binfmt.service loaded active exited Set Up Additional Binary Formats
systemd-fsck-root.service loaded active exited File System Check on Root Device
systemd-fsck@dev-disk-by\x2dlabel-BOOT.service loaded active exited File System Check on /dev/disk/by-label/BOOT
systemd-fsck@dev-disk-by\x2dlabel-UEFI.service loaded active exited File System Check on /dev/disk/by-label/UEFI
systemd-journal-flush.service loaded active exited Flush Journal to Persistent Storage
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running User Login Management
systemd-modules-load.service loaded active exited Load Kernel Modules
systemd-networkd-wait-online.service loaded active exited Wait for Network to be Configured
systemd-networkd.service loaded active running Network Configuration
systemd-random-seed.service loaded active exited Load/Save OS Random Seed
systemd-remount-fs.service loaded active exited Remount Root and Kernel File Systems
systemd-resolved.service loaded active running Network Name Resolution
systemd-sysctl.service loaded active exited Apply Kernel Variables
systemd-tmpfiles-setup-dev-early.service loaded active exited Create Static Device Nodes in /dev gracefully
systemd-tmpfiles-setup-dev.service loaded active exited Create Static Device Nodes in /dev
systemd-tmpfiles-setup.service loaded active exited Create Volatile Files and Directories
systemd-udev-trigger.service loaded active exited Coldplug All udev Devices
systemd-udevd.service loaded active running Rule-based Manager for Device Events and Files
systemd-update-utmp.service loaded active exited Record System Boot/Shutdown in UTMP
systemd-user-sessions.service loaded active exited Permit User Sessions
udisks2.service loaded active running Disk Manager
ufw.service loaded active exited Uncomplicated firewall
unattended-upgrades.service loaded active running Unattended Upgrades Shutdown
user-runtime-dir@1000.service loaded active exited User Runtime Directory /run/user/1000
user@1000.service loaded active running User Manager for UID 1000
Legend: LOAD → Reflects whether the unit definition was properly loaded.
ACTIVE → The high-level unit activation state, i.e. generalization of SUB.
SUB → The low-level unit activation state, values depend on unit type.
65 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
/home/isucon/.local/go/bin:/home/isucon/.local/node/bin:/home/isucon/.local/ruby/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ sudo systemctl disable --now isu-ruby
Removed "/etc/systemd/system/multi-user.target.wants/isu-ruby.service".
$ sudo systemctl enable --now isu-go
Created symlink /etc/systemd/system/multi-user.target.wants/isu-go.service → /etc/systemd/system/isu-go.service.
$ /home/isucon/private_isu.git/benchmarker/bin/benchmarker -u /home/isucon/private_isu.git/benchmarker/userdata -t http://172.31.29.227
{"pass":true,"score":4187,"success":4028,"fail":0,"messages":[]}
# A software update is available:
# 2.6s user time, 140ms system time, 73.38M rss, 392.17G vsz
# Current date: Sat Aug 24 11:23:11 2024
# Hostname: salmon.local
# Files: mysql-slow.log
# Overall: 71.48k total, 27 unique, 850.98 QPS, 7.42x concurrency ________
# Time range: 2024-08-24T02:21:30 to 2024-08-24T02:22:54
# Attribute total min max avg 95% stddev median
# ============ ======= ======= ======= ======= ======= ======= =======
# Exec time 624s 1us 306ms 9ms 59ms 29ms 31us
# Lock time 32ms 0 7ms 0 1us 28us 0
# Rows sent 1.32M 0 9.77k 19.32 0.99 414.76 0
# Rows examine 666.05M 0 97.68k 9.54k 97.04k 28.75k 0
# Query size 7.99M 17 1.15M 117.23 72.65 8.57k 31.70
# Profile
# Rank Query ID Response time Calls R/Call V/M
# ==== =================================== ============== ===== ====== ===
# 1 0x624863D30DAC59FA16849282195BE09F 396.0856 63.5% 3207 0.1235 0.01 SELECT comments
# 2 0x422390B42D4DD86C7539A5F45EB76A80 163.0011 26.1% 3443 0.0473 0.00 SELECT comments
# 3 0x100EC8B5C400F34381F9D7F7FA80A53D 32.4159 5.2% 236 0.1374 0.00 SELECT comments
# 4 0x19759A5557089FD5B718D440CBBB5C55 18.2332 2.9% 2520 0.0072 0.12 SELECT posts
# MISC 0xMISC 13.8612 2.2% 62076 0.0002 0.0 <23 ITEMS>
# Query 1: 38.18 QPS, 4.72x concurrency, ID 0x624863D30DAC59FA16849282195BE09F at byte 6405454
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.01
# Time range: 2024-08-24T02:21:30 to 2024-08-24T02:22:54
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 4 3207
# Exec time 63 396s 26ms 204ms 124ms 148ms 33ms 128ms
# Lock time 9 3ms 0 438us 0 1us 7us 1us
# Rows sent 0 8.01k 0 3 2.56 2.90 1.03 2.90
# Rows examine 45 305.87M 97.66k 97.67k 97.66k 97.04k 0 97.04k
# Query size 3 257.35k 80 83 82.17 80.10 0.12 80.10
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms ########
# 100ms ################################################################
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'comments'\G
# SHOW CREATE TABLE `isuconp`.`comments`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM `comments` WHERE `post_id` = 6857 ORDER BY `created_at` DESC LIMIT 3\G
# Query 2: 40.99 QPS, 1.94x concurrency, ID 0x422390B42D4DD86C7539A5F45EB76A80 at byte 12132827
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: 2024-08-24T02:21:30 to 2024-08-24T02:22:54
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 4 3443
# Exec time 26 163s 10ms 91ms 47ms 61ms 13ms 48ms
# Lock time 7 3ms 0 16us 0 1us 0 1us
# Rows sent 0 3.36k 1 1 1 1 0 1
# Rows examine 49 328.37M 97.66k 97.67k 97.66k 97.04k 0 97.04k
# Query size 2 219.08k 63 66 65.16 65.89 1.19 62.76
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms ################################################################
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'comments'\G
# SHOW CREATE TABLE `isuconp`.`comments`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT COUNT(*) AS `count` FROM `comments` WHERE `post_id` = 8908\G
# Query 3: 3.52 QPS, 0.48x concurrency, ID 0x100EC8B5C400F34381F9D7F7FA80A53D at byte 12086969
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: 2024-08-24T02:21:31 to 2024-08-24T02:22:38
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 0 236
# Exec time 5 32s 27ms 190ms 137ms 155ms 17ms 134ms
# Lock time 0 193us 0 2us 0 1us 0 1us
# Rows sent 0 2.19k 0 20 9.52 14.52 3.59 8.91
# Rows examine 3 22.51M 97.66k 97.68k 97.67k 97.04k 0 97.04k
# Query size 0 17.04k 72 75 73.95 72.65 0.22 72.65
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms #
# 100ms ################################################################
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'comments'\G
# SHOW CREATE TABLE `isuconp`.`comments`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM `comments` WHERE `post_id` = 205 ORDER BY `created_at` DESC\G
# Query 4: 34.52 QPS, 0.25x concurrency, ID 0x19759A5557089FD5B718D440CBBB5C55 at byte 2288990
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.12
# Time range: 2024-08-24T02:21:31 to 2024-08-24T02:22:44
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 3 2520
# Exec time 2 18s 60us 306ms 7ms 75ms 29ms 113us
# Lock time 7 2ms 0 170us 0 1us 3us 1us
# Rows sent 0 2.46k 1 1 1 1 0 1
# Rows examine 0 2.46k 1 1 1 1 0 1
# Query size 1 96.29k 37 40 39.13 38.53 0.27 38.53
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us ##################################
# 100us ################################################################
# 1ms ####
# 10ms ##
# 100ms ####
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'posts'\G
# SHOW CREATE TABLE `isuconp`.`posts`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM `posts` WHERE `id` = 7209\G
mysql> explain SELECT * FROM `comments` WHERE `post_id` = 6857 ORDER BY `created_at` DESC LIMIT 3;
+----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| 1 | SIMPLE | comments | NULL | ALL | NULL | NULL | NULL | NULL | 99674 | 10.00 | Using where; Using filesort |
+----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> ALTER TABLE comments ADD INDEX (post_id, created_at DESC);
Query OK, 0 rows affected (0.14 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain SELECT * FROM `comments` WHERE `post_id` = 6857 ORDER BY `created_at` DESC LIMIT 3;
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | comments | NULL | ref | post_id | post_id | 4 | const | 10 | 100.00 | NULL |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
$ /home/isucon/private_isu.git/benchmarker/bin/benchmarker -u /home/isucon/private_isu.git/benchmarker/userdata -t http://172.31.29.227
{"pass":true,"score":34788,"success":32613,"fail":0,"messages":[]}
Top 20 Sort By Total
Count Total Mean Stddev Min P50.0 P90.0 P95.0 P99.0 Max 2xx 3xx 4xx 5xx TotalBytes MinBytes MeanBytes MaxBytes Request
1266 227.148 0.1794 0.0375 0.030 0.176 0.229 0.244 0.278 0.328 1266 0 0 0 3932113 2639 3105 6045 GET / HTTP/1.1
19602 163.539 0.0083 0.0123 0.000 0.005 0.016 0.022 0.044 0.327 19602 0 0 0 6313515243 34642 322085 1057912 GET /image/$image
240 72.038 0.3002 0.0464 0.064 0.300 0.353 0.365 0.409 0.432 240 0 0 0 1281443 5032 5339 5773 GET /posts?max_created_at=(.*)
1470 50.410 0.0343 0.0204 0.002 0.030 0.059 0.070 0.101 0.215 1470 0 0 0 1892691 712 1287 1981 GET /posts/\d+
247 47.725 0.1932 0.0493 0.030 0.191 0.257 0.271 0.319 0.339 247 0 0 0 822301 1590 3329 5380 GET /@[a-zA-Z0-9]+
930 25.879 0.0278 0.0140 0.000 0.027 0.046 0.051 0.062 0.096 0 930 0 0 0 0 0 0 POST /login HTTP/1.1
244 5.002 0.0205 0.0192 0.001 0.011 0.049 0.057 0.082 0.086 0 122 122 0 0 0 0 0 POST / HTTP/1.1
141 4.809 0.0341 0.0127 0.010 0.032 0.051 0.057 0.081 0.082 0 141 0 0 0 0 0 0 POST /register HTTP/1.1
1951 4.147 0.0021 0.0028 0.000 0.001 0.005 0.007 0.014 0.029 1951 0 0 0 83893 43 43 43 GET /favicon.ico HTTP/1.1
1951 4.042 0.0021 0.0030 0.000 0.001 0.005 0.007 0.015 0.030 1951 0 0 0 3736165 1915 1915 1915 GET /js/timeago.min.js HTTP/1.1
1951 3.707 0.0019 0.0025 0.000 0.001 0.004 0.006 0.013 0.023 1951 0 0 0 3022099 1549 1549 1549 GET /css/style.css HTTP/1.1
1951 3.689 0.0019 0.0029 0.000 0.001 0.004 0.007 0.015 0.035 1951 0 0 0 3558624 1824 1824 1824 GET /js/main.js HTTP/1.1
128 1.351 0.0106 0.0084 0.001 0.008 0.020 0.028 0.047 0.049 0 128 0 0 0 0 0 0 POST /comment HTTP/1.1
278 1.281 0.0046 0.0052 0.000 0.003 0.011 0.016 0.028 0.038 278 0 0 0 170970 615 615 615 GET /login HTTP/1.1
141 0.997 0.0071 0.0065 0.000 0.005 0.016 0.019 0.035 0.041 0 0 141 0 0 0 0 0 GET /admin/banned HTTP/1.1
139 0.504 0.0036 0.0035 0.000 0.003 0.008 0.010 0.018 0.026 0 139 0 0 3336 24 24 24 GET /logout HTTP/1.1
1 0.056 0.0560 0.0000 0.056 0.056 0.056 0.056 0.056 0.056 1 0 0 0 0 0 0 0 GET /initialize HTTP/1.1
MySQLが一番頑張っている
GET /image/$image
posts
テーブルの img_data
カラムに画像が載っている
データをファイルに落とし、Nginxから直接返せるようにしていく
現時点のスコア
{"pass":true,"score":35575,"success":33419,"fail":0,"messages":[]}
ベンチ中にハングしたのでAWS Consoleから強制停止 & 起動させて、Swap 2GB追加 💀
{"pass":true,"score":57371,"success":54852,"fail":0,"messages":[]}
ついでにinvisible化
mysql> ALTER TABLE posts MODIFY COLUMN `imgdata` mediumblob NOT NULL
INVISIBLE;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
{"pass":true,"score":58891,"success":56339,"fail":0,"messages":[]}
Top 20 Sort By Total
Count Total Mean Stddev Min P50.0 P90.0 P95.0 P99.0 Max 2xx 3xx 4xx 5xx TotalBytes MinBytes MeanBytes MaxBytes Request
1833 339.612 0.1853 0.0345 0.031 0.184 0.229 0.245 0.271 0.299 1833 0 0 0 5594720 2653 3052 6038 GET / HTTP/1.1
360 111.834 0.3107 0.0647 0.037 0.320 0.375 0.386 0.410 0.422 360 0 0 0 1928370 4962 5356 5878 GET /posts?max_created_at=(.*)
2322 76.137 0.0328 0.0196 0.001 0.028 0.060 0.070 0.087 0.133 2322 0 0 0 3008011 713 1295 1908 GET /posts/\d+
334 67.728 0.2028 0.0492 0.028 0.201 0.264 0.282 0.323 0.331 334 0 0 0 1083597 1567 3244 5053 GET /@[a-zA-Z0-9]+
1294 33.550 0.0259 0.0151 0.000 0.025 0.046 0.053 0.068 0.087 0 1294 0 0 0 0 0 0 POST /login HTTP/1.1
137 4.747 0.0346 0.0163 0.010 0.031 0.054 0.060 0.097 0.111 0 137 0 0 0 0 0 0 POST /register HTTP/1.1
248 3.438 0.0139 0.0134 0.001 0.010 0.030 0.039 0.055 0.112 0 124 124 0 0 0 0 0 POST / HTTP/1.1
520 2.086 0.0040 0.0048 0.000 0.002 0.010 0.015 0.022 0.035 520 0 0 0 319800 615 615 615 GET /login HTTP/1.1
129 1.236 0.0096 0.0106 0.001 0.006 0.023 0.036 0.046 0.056 0 129 0 0 0 0 0 0 POST /comment HTTP/1.1
260 1.215 0.0047 0.0059 0.000 0.002 0.013 0.017 0.030 0.035 0 260 0 0 6240 24 24 24 GET /logout HTTP/1.1
137 0.799 0.0058 0.0076 0.000 0.003 0.013 0.022 0.038 0.052 0 0 137 0 0 0 0 0 GET /admin/banned HTTP/1.1
35102 0.464 0.0000 0.0011 0.000 0.000 0.000 0.000 0.000 0.182 2191 32911 0 0 325390406 0 9269 1089626 GET /image/$image
1 0.228 0.2280 0.0000 0.228 0.228 0.228 0.228 0.228 0.228 1 0 0 0 22374 22374 22374 22374 GET / HTTP/1.0
1 0.012 0.0120 0.0000 0.012 0.012 0.012 0.012 0.012 0.012 1 0 0 0 0 0 0 0 GET /initialize HTTP/1.1
3455 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 3454 0 0 1824 0 0 1824 GET /js/main.js HTTP/1.1
3455 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 3454 0 0 1549 0 0 1549 GET /css/style.css HTTP/1.1
3455 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 3454 0 0 43 0 0 43 GET /favicon.ico HTTP/1.1
3455 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 3454 0 0 1915 0 0 1915 GET /js/timeago.min.js HTTP/1.1
mysql> explain SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` WHERE `created_at` <= '2016-01-02T11:46:03+09:00' ORDER BY `created_at` DESC;
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| 1 | SIMPLE | posts | NULL | ALL | NULL | NULL | NULL | NULL | 10214 | 33.33 | Using where; Using filesort |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> ALTER TABLE posts ADD INDEX (created_at);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` WHERE `created_at` <= '2016-01-02T11:46:03+09:00' ORDER BY `created_at` DESC;
+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------------------------------------------------------+
| 1 | SIMPLE | posts | NULL | range | created_at | created_at | 4 | NULL | 9963 | 100.00 | Using index condition; Backward index scan; Using MRR |
+----+-------------+-------+------------+-------+---------------+------------+---------+------+------+----------+-------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> explain SELECT COUNT(*) AS count FROM `comments` WHERE `user_id` = 433;
+----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| 1 | SIMPLE | comments | NULL | ALL | NULL | NULL | NULL | NULL | 99667 | 10.00 | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> ALTER TABLE comments ADD INDEX (user_id);
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain SELECT COUNT(*) AS count FROM `comments` WHERE `user_id` = 433;
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | comments | NULL | ref | user_id | user_id | 4 | const | 96 | 100.00 | Using index |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
{"pass":true,"score":60042,"success":57444,"fail":0,"messages":[]}
top-slow 1位のクエリがpostsを全件取ってそうで怪しい
# Query 1: 5.46 QPS, 0.18x concurrency, ID 0x4858CF4D8CAA743E839C127C71B69E75 at byte 758735
# Scores: V/M = 0.00
# Time range: 2024-09-16T02:17:36 to 2024-09-16T02:23:12
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 0 1835
# Exec time 52 59s 11ms 65ms 32ms 48ms 9ms 31ms
# Lock time 2 4ms 0 2ms 2us 1us 45us 1us
# Rows sent 82 17.61M 9.77k 9.89k 9.83k 9.80k 62 9.80k
# Rows examine 43 35.22M 19.53k 19.77k 19.65k 19.40k 0 19.40k
# Query size 0 164.86k 92 92 92 92 0 92
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms ################################################################
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'posts'\G
# SHOW CREATE TABLE `isuconp`.`posts`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` ORDER BY `created_at` DESC\G
↑ 後続処理の makePosts()
内で、未削除20件に絞る処理があった
一旦雑に、余裕を持って LIMIT 30
に設定
b308429
{"pass":true,"score":95790,"success":91478,"fail":0,"messages":[]}
Top 20 Sort By Total
Count Total Mean Stddev Min P50.0 P90.0 P95.0 P99.0 Max 2xx 3xx 4xx 5xx TotalBytes MinBytes MeanBytes MaxBytes Request
3144 305.764 0.0973 0.0224 0.017 0.095 0.126 0.136 0.168 0.192 3144 0 0 0 9089033 2601 2890 6046 GET / HTTP/1.1
520 111.467 0.2144 0.0287 0.037 0.218 0.240 0.246 0.265 0.337 520 0 0 0 2778291 4985 5342 5827 GET /posts?max_created_at=(.*)
3543 80.408 0.0227 0.0120 0.002 0.020 0.038 0.047 0.064 0.090 3543 0 0 0 4578461 696 1292 1931 GET /posts/\d+
530 60.738 0.1146 0.0343 0.017 0.115 0.160 0.174 0.195 0.266 530 0 0 0 1713098 1485 3232 5312 GET /@[a-zA-Z0-9]+
2171 50.185 0.0231 0.0121 0.000 0.024 0.038 0.042 0.051 0.073 0 2171 0 0 0 0 0 0 POST /login HTTP/1.1
233 7.131 0.0306 0.0110 0.010 0.030 0.044 0.051 0.069 0.082 0 233 0 0 0 0 0 0 POST /register HTTP/1.1
422 4.573 0.0108 0.0080 0.001 0.009 0.021 0.027 0.039 0.046 0 211 211 0 0 0 0 0 POST / HTTP/1.1
864 2.309 0.0027 0.0029 0.000 0.002 0.005 0.008 0.016 0.026 864 0 0 0 531360 615 615 615 GET /login HTTP/1.1
220 1.281 0.0058 0.0046 0.000 0.005 0.010 0.016 0.028 0.031 0 220 0 0 0 0 0 0 POST /comment HTTP/1.1
432 1.078 0.0025 0.0027 0.000 0.002 0.005 0.007 0.014 0.023 0 432 0 0 10368 24 24 24 GET /logout HTTP/1.1
233 0.981 0.0042 0.0039 0.001 0.003 0.007 0.009 0.019 0.034 0 0 233 0 0 0 0 0 GET /admin/banned HTTP/1.1
57555 0.147 0.0000 0.0001 0.000 0.000 0.000 0.000 0.000 0.008 3038 54517 0 0 462954215 0 8043 1265181 GET /image/$image
1 0.013 0.0130 0.0000 0.013 0.013 0.013 0.013 0.013 0.013 1 0 0 0 0 0 0 0 GET /initialize HTTP/1.1
5458 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 5457 0 0 1915 0 0 1915 GET /js/timeago.min.js HTTP/1.1
5458 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 5457 0 0 1549 0 0 1549 GET /css/style.css HTTP/1.1
5458 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 5457 0 0 1824 0 0 1824 GET /js/main.js HTTP/1.1
5458 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 5457 0 0 43 0 0 43 GET /favicon.ico HTTP/1.1
動的プレースホルダを使うように設定 ✅
{"pass":true,"score":114162,"success":109182,"fail":0,"messages":[]}
ついでにコネクションプーリングの設定 ✅
{"pass":true,"score":119715,"success":114429,"fail":0,"messages":[]}
# Query 1: 2.40 QPS, 0.10x concurrency, ID 0x7A12D0C8F433684C3027353C36CAB572 at byte 162930666
# Scores: V/M = 0.00
# Time range: 2024-09-16T02:45:05 to 2024-09-16T02:53:58
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 0 1280
# Exec time 32 52s 16ms 80ms 41ms 56ms 9ms 40ms
# Lock time 0 1ms 0 37us 0 1us 1us 1us
# Rows sent 91 12.08M 9.57k 9.76k 9.66k 9.33k 0 9.33k
# Rows examine 30 12.08M 9.57k 9.76k 9.66k 9.33k 0 9.33k
# Query size 0 177.50k 142 142 142 142 0 142
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms ################################################################
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'posts'\G
# SHOW CREATE TABLE `isuconp`.`posts`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` WHERE `created_at` <= '2016-01-02T11:45:49+09:00' ORDER BY `created_at` DESC\G
63cc2b1
{"pass":true,"score":145909,"success":139864,"fail":0,"messages":[]}
休憩 12:20 - 14:30 あと4時間くらい
# Query 1: 4.45k QPS, 0.40x concurrency, ID 0x396201721CD58410E070DA9421CA8C8D at byte 25204635
# Scores: V/M = 0.00
# Time range: 2024-09-16T03:11:27 to 2024-09-16T03:12:28
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 50 271191
# Exec time 35 25s 25us 7ms 90us 287us 154us 52us
# Lock time 49 229ms 0 3ms 0 1us 13us 1us
# Rows sent 37 264.83k 1 1 1 1 0 1
# Rows examine 1 264.83k 1 1 1 1 0 1
# Query size 33 9.80M 36 39 37.89 36.69 0.16 36.69
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us ################################################################
# 100us #########
# 1ms #
# 10ms
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'users'\G
# SHOW CREATE TABLE `isuconp`.`users`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM `users` WHERE `id` = 729\G
レコード数は1.5kレコード程度なので、全部メモリで持つかたちにする
mysql> select count(*) from users;
+----------+
| count(*) |
+----------+
| 1340 |
+----------+
1 row in set (0.00 sec)
{"pass":true,"score":200467,"success":193708,"fail":0,"messages":[]}
# Query 1: 2.56k QPS, 0.35x concurrency, ID 0x624863D30DAC59FA16849282195BE09F at byte 13433422
# Scores: V/M = 0.00
# Time range: 2024-09-16T06:50:25 to 2024-09-16T06:51:25
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 43 153505
# Exec time 32 21s 39us 11ms 138us 445us 203us 80us
# Lock time 41 140ms 0 2ms 0 1us 11us 1us
# Rows sent 23 151.47k 0 3 1.01 2.90 1.36 0
# Rows examine 0 151.47k 0 3 1.01 2.90 1.36 0
# Query size 48 12.10M 79 83 82.66 80.10 0.11 80.10
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us ################################################################
# 100us #######################
# 1ms #
# 10ms #
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'comments'\G
# SHOW CREATE TABLE `isuconp`.`comments`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM `comments` WHERE `post_id` = 15228 ORDER BY `created_at` DESC LIMIT 3\G
クエリ発行回数的にN+1だが、post_idごとにLIMIT 3する上手い方法がパッと思いつかないので後回し
# Query 2: 2.71k QPS, 0.35x concurrency, ID 0x422390B42D4DD86C7539A5F45EB76A80 at byte 6804912
# Scores: V/M = 0.00
# Time range: 2024-09-16T06:50:25 to 2024-09-16T06:51:25
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 45 162582
# Exec time 31 21s 38us 5ms 127us 403us 184us 76us
# Lock time 46 156ms 0 2ms 0 1us 15us 1us
# Rows sent 24 158.77k 1 1 1 1 0 1
# Rows examine 2 582.02k 0 23 3.67 12.54 5.06 0
# Query size 40 10.17M 62 66 65.62 65.89 1.51 65.89
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us ################################################################
# 100us ##################
# 1ms #
# 10ms
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'comments'\G
# SHOW CREATE TABLE `isuconp`.`comments`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT COUNT(*) AS `count` FROM `comments` WHERE `post_id` = 15209\G
これもN+1 パッと直せそうなので見ていく
{"pass":true,"score":233499,"success":225669,"fail":0,"messages":[]}
引き続き1位は一旦skip
# Query 2: 20.90 QPS, 0.21x concurrency, ID 0xE83DA93257C7B787C67B1B05D2469241 at byte 30132196
# Scores: V/M = 0.00
# Time range: 2024-09-16T06:54:46 to 2024-09-16T06:55:46
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 0 1254
# Exec time 23 13s 3ms 24ms 10ms 16ms 4ms 9ms
# Lock time 0 1ms 0 278us 1us 1us 9us 1us
# Rows sent 1 12.53k 2 21 10.23 14.52 2.92 9.83
# Rows examine 46 12.20M 9.77k 10.14k 9.96k 9.80k 109.66 9.80k
# Query size 0 139.50k 113 114 113.91 112.70 0 112.70
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms ################################################################
# 10ms ##############################################################
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'posts'\G
# SHOW CREATE TABLE `isuconp`.`posts`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` WHERE `user_id` = 641 ORDER BY `created_at` DESC\G
index張れそう
mysql> explain SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` WHERE `user_id` = 641 ORDER BY `created_at` DESC;
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
| 1 | SIMPLE | posts | NULL | ALL | NULL | NULL | NULL | NULL | 10315 | 10.00 | Using where; Using filesort |
+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> ALTER TABLE posts ADD INDEX (user_id, created_at DESC);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` WHERE `user_id` = 641 ORDER BY `created_at` DESC;
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | posts | NULL | ref | user_id | user_id | 4 | const | 11 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
{"pass":true,"score":244925,"success":236644,"fail":0,"messages":[]}
申し訳程度 4536f163ca1df04615644fa03de0ae1898281d67
{"pass":true,"score":248304,"success":240071,"fail":0,"messages":[]}
Top 20 Sort By Total
Count Total Mean Stddev Min P50.0 P90.0 P95.0 P99.0 Max 2xx 3xx 4xx 5xx TotalBytes MinBytes MeanBytes MaxBytes Request
6764 226.622 0.0335 0.0085 0.004 0.033 0.045 0.048 0.056 0.074 6764 0 0 0 19319055 2552 2856 6049 GET / HTTP/1.1
4106 95.422 0.0232 0.0118 0.000 0.025 0.038 0.040 0.046 0.078 0 4106 0 0 0 0 0 0 POST /login HTTP/1.1
2320 90.017 0.0388 0.0092 0.003 0.038 0.050 0.054 0.063 0.092 2320 0 0 0 12419660 4965 5353 5852 GET /posts?max_created_at=(.*)
9917 69.076 0.0070 0.0037 0.001 0.006 0.012 0.014 0.019 0.030 9917 0 0 0 12868655 693 1297 2104 GET /posts/\d+
1471 40.109 0.0273 0.0090 0.007 0.026 0.039 0.043 0.052 0.074 1471 0 0 0 4749940 1423 3229 5538 GET /@[a-zA-Z0-9]+
472 13.533 0.0287 0.0083 0.009 0.029 0.039 0.042 0.051 0.061 0 472 0 0 0 0 0 0 POST /register HTTP/1.1
768 8.336 0.0109 0.0080 0.000 0.009 0.022 0.025 0.035 0.054 0 384 384 0 0 0 0 0 POST / HTTP/1.1
1522 5.300 0.0035 0.0025 0.000 0.003 0.007 0.009 0.012 0.019 1522 0 0 0 936030 615 615 615 GET /login HTTP/1.1
761 2.894 0.0038 0.0030 0.000 0.003 0.008 0.010 0.015 0.023 0 761 0 0 18264 24 24 24 GET /logout HTTP/1.1
583 2.300 0.0039 0.0027 0.000 0.003 0.007 0.009 0.013 0.021 0 583 0 0 0 0 0 0 POST /comment HTTP/1.1
472 1.107 0.0023 0.0021 0.000 0.002 0.005 0.006 0.011 0.013 0 0 472 0 0 0 0 0 GET /admin/banned HTTP/1.1
154064 0.322 0.0000 0.0001 0.000 0.000 0.000 0.000 0.000 0.005 6331 147733 0 0 943677578 0 6125 1265181 GET /image/$image
1 0.016 0.0160 0.0000 0.016 0.016 0.016 0.016 0.016 0.016 1 0 0 0 0 0 0 0 GET /initialize HTTP/1.1
14307 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 14306 0 0 1915 0 0 1915 GET /js/timeago.min.js HTTP/1.1
14307 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 14306 0 0 1824 0 0 1824 GET /js/main.js HTTP/1.1
14307 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 14306 0 0 1549 0 0 1549 GET /css/style.css HTTP/1.1
14307 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 14306 0 0 43 0 0 43 GET /favicon.ico HTTP/1.1
# Query 1: 3.30k QPS, 0.45x concurrency, ID 0x624863D30DAC59FA16849282195BE09F at byte 38574882
# Scores: V/M = 0.00
# Time range: 2024-09-16T07:14:08 to 2024-09-16T07:15:08
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 75 198075
# Exec time 67 27s 39us 6ms 136us 424us 191us 80us
# Lock time 72 196ms 0 2ms 0 1us 14us 1us
# Rows sent 27 196.29k 0 3 1.01 2.90 1.36 0
# Rows examine 10 196.29k 0 3 1.01 2.90 1.36 0
# Query size 69 15.61M 79 83 82.66 80.10 0.10 80.10
# String:
# Databases isuconp
# Hosts localhost
# Users isuconp
# Query_time distribution
# 1us
# 10us ################################################################
# 100us ##########################
# 1ms #
# 10ms
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `isuconp` LIKE 'comments'\G
# SHOW CREATE TABLE `isuconp`.`comments`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT * FROM `comments` WHERE `post_id` = 9918 ORDER BY `created_at` DESC LIMIT 3\G
サブクエリでwindow関数を使ってrownumを振り、元クエリでrownumが3以下のものだけを取るようにすれば欲しいものが取れる
{"pass":true,"score":321739,"success":312564,"fail":0,"messages":[]}
slow query見た感じ、もうクエリ的にはチューニングの余地無さそうなのでDBは一旦終わりの設定に
{"pass":true,"score":329460,"success":320070,"fail":0,"messages":[]}
(pprof) list getIndex
Total: 1881.62s
ROUTINE ======================== main.getIndex in /home/isucon/isucon-practice-20240824-private-isu/webapp/golang/app.go
0 82.61s (flat, cum) 4.39% of Total
. . 427:
. . 428: http.Redirect(w, r, "/", http.StatusFound)
. . 429:}
. . 430:
. . 431:func getIndex(w http.ResponseWriter, r *http.Request) {
. 5.71s 432: me := getSessionUser(r)
. . 433:
. . 434: results := []Post{}
. . 435:
. 23.14s 436: err := db.Select(&results, "SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` ORDER BY `created_at` DESC LIMIT 30")
. . 437: if err != nil {
. . 438: log.Print(err)
. . 439: return
. . 440: }
. . 441:
. 46.25s 442: posts, err := makePosts(results, getCSRFToken(r), false)
. . 443: if err != nil {
. . 444: log.Print(err)
. . 445: return
. . 446: }
. . 447:
. . 448: fmap := template.FuncMap{
. . 449: "imageURL": imageURL,
. . 450: }
. . 451:
. 1.56s 452: template.Must(template.New("layout.html").Funcs(fmap).ParseFiles(
. 10.10ms 453: getTemplPath("layout.html"),
. . 454: getTemplPath("index.html"),
. . 455: getTemplPath("posts.html"),
. . 456: getTemplPath("post.html"),
. 5.93s 457: )).Execute(w, struct {
. . 458: Posts []Post
. . 459: Me User
. . 460: CSRFToken string
. . 461: Flash string
. 10.10ms 462: }{posts, me, getCSRFToken(r), getFlash(w, r, "notice")})
. . 463:}
. . 464:
. . 465:func getAccountName(w http.ResponseWriter, r *http.Request) {
. . 466: accountName := r.PathValue("accountName")
. . 467: user := User{}
(pprof) list getSessionUser
Total: 1881.62s
ROUTINE ======================== main.getSessionUser in /home/isucon/isucon-practice-20240824-private-isu/webapp/golang/app.go
0 10.42s (flat, cum) 0.55% of Total
. . 144:
. . 145: return session
. . 146:}
. . 147:
. . 148:func getSessionUser(r *http.Request) User {
. 9.16s 149: session := getSession(r)
. . 150: uid, ok := session.Values["user_id"]
. . 151: if !ok || uid == nil {
. . 152: return User{}
. . 153: }
. . 154:
. . 155: id := 0
. . 156: switch value := uid.(type) {
. . 157: case int:
. . 158: id = value
. . 159: case int64:
. . 160: id = int(value)
. . 161: }
. 1.26s 162: u, err := findUser(id)
. . 163: if err != nil {
. . 164: return User{}
. . 165: }
. . 166:
. . 167: return u
session storeにmemcacheを使っているっぽい cookie storeに変えてみる
{"pass":true,"score":317982,"success":308171,"fail":1,"messages":["静的ファイルが正しくありません (GET /image/18743.png)"]}
スコア下がったのでやめ
(pprof) list postLogin
Total: 1881.62s
ROUTINE ======================== main.postLogin in /home/isucon/isucon-practice-20240824-private-isu/webapp/golang/app.go
0 104.17s (flat, cum) 5.54% of Total
. . 328: Flash string
. . 329: }{me, getFlash(w, r, "notice")})
. . 330:}
. . 331:
. . 332:func postLogin(w http.ResponseWriter, r *http.Request) {
. 10.10ms 333: if isLogin(getSessionUser(r)) {
. . 334: http.Redirect(w, r, "/", http.StatusFound)
. . 335: return
. . 336: }
. . 337:
. 97.21s 338: u := tryLogin(r.FormValue("account_name"), r.FormValue("password"))
. . 339:
. . 340: if u != nil {
. . 341: session := getSession(r)
. . 342: session.Values["user_id"] = u.ID
. . 343: session.Values["csrf_token"] = secureRandomStr(16)
. 4.39s 344: session.Save(r, w)
. . 345:
. . 346: http.Redirect(w, r, "/", http.StatusFound)
. . 347: } else {
. . 348: session := getSession(r)
. . 349: session.Values["notice"] = "アカウント名かパスワードが間違っています"
. 2.56s 350: session.Save(r, w)
. . 351:
. . 352: http.Redirect(w, r, "/login", http.StatusFound)
. . 353: }
. . 354:}
. . 355:
(pprof) list tryLogin
Total: 1881.62s
ROUTINE ======================== main.tryLogin in /home/isucon/isucon-practice-20240824-private-isu/webapp/golang/app.go
0 97.16s (flat, cum) 5.16% of Total
. . 94: }
. . 95:}
. . 96:
. . 97:func tryLogin(accountName, password string) *User {
. . 98: u := User{}
. 9.98s 99: err := db.Get(&u, "SELECT * FROM users WHERE account_name = ? AND del_flg = 0", accountName)
. . 100: if err != nil {
. . 101: return nil
. . 102: }
. . 103:
. 87.18s 104: if calculatePasshash(u.AccountName, password) == u.Passhash {
. . 105: return &u
. . 106: } else {
. . 107: return nil
. . 108: }
. . 109:}
(pprof) list calculatePasshash
Total: 1881.62s
ROUTINE ======================== main.calculatePasshash in /home/isucon/isucon-practice-20240824-private-isu/webapp/golang/app.go
0 100.12s (flat, cum) 5.32% of Total
. . 134:func calculateSalt(accountName string) string {
. . 135: return digest(accountName)
. . 136:}
. . 137:
. . 138:func calculatePasshash(accountName, password string) string {
. 100.12s 139: return digest(password + ":" + calculateSalt(accountName))
. . 140:}
. . 141:
. . 142:func getSession(r *http.Request) *sessions.Session {
. . 143: session, _ := store.Get(r, "isuconp-go.session")
. . 144:
(pprof) list digest
Total: 1881.62s
ROUTINE ======================== crypto/sha256.(*digest).Write in /home/isucon/.local/go/src/crypto/sha256/sha256.go
10.10ms 10.10ms (flat, cum) 0.00054% of Total
. . 174: return Size224
. . 175:}
. . 176:
. . 177:func (d *digest) BlockSize() int { return BlockSize }
. . 178:
10.10ms 10.10ms 179:func (d *digest) Write(p []byte) (nn int, err error) {
. . 180: boring.Unreachable()
. . 181: nn = len(p)
. . 182: d.len += uint64(nn)
. . 183: if d.nx > 0 {
. . 184: n := copy(d.x[d.nx:], p)
ROUTINE ======================== main.digest in /home/isucon/isucon-practice-20240824-private-isu/webapp/golang/app.go
0 100.11s (flat, cum) 5.32% of Total
. . 120: return "'" + strings.Replace(arg, "'", "'\\''", -1) + "'"
. . 121:}
. . 122:
. . 123:func digest(src string) string {
. . 124: // opensslのバージョンによっては (stdin)= というのがつくので取る
. 100.11s 125: out, err := exec.Command("/bin/bash", "-c", `printf "%s" `+escapeshellarg(src)+` | openssl dgst -sha512 | sed 's/^.*= //'`).Output()
. . 126: if err != nil {
. . 127: log.Print(err)
. . 128: return ""
. . 129: }
. . 130:
digest計算で外部コマンドを呼び出しているのをGoのlibraryでなんとかしたい
{"pass":true,"score":508788,"success":486772,"fail":0,"messages":[]}
Top 20 Sort By Total
Count Total Mean Stddev Min P50.0 P90.0 P95.0 P99.0 Max 2xx 3xx 4xx 5xx TotalBytes MinBytes MeanBytes MaxBytes Request
17864 152.115 0.0085 0.0037 0.001 0.008 0.013 0.015 0.020 0.033 17864 0 0 0 48835181 2460 2733 6040 GET / HTTP/1.1
12706 81.592 0.0064 0.0033 0.000 0.006 0.011 0.013 0.016 0.038 12706 0 0 0 15867346 706 1248 1989 GET /posts/\d+
5190 62.934 0.0121 0.0043 0.002 0.012 0.017 0.019 0.023 0.100 5190 0 0 0 27710273 4947 5339 5826 GET /posts?max_created_at=(.*)
10902 40.167 0.0037 0.0025 0.000 0.003 0.007 0.009 0.012 0.021 0 10902 0 0 0 0 0 0 POST /login HTTP/1.1
2435 34.346 0.0141 0.0055 0.002 0.014 0.021 0.024 0.028 0.063 2435 0 0 0 8022475 1339 3294 5569 GET /@[a-zA-Z0-9]+
2110 18.530 0.0088 0.0079 0.000 0.006 0.019 0.022 0.045 0.062 0 1055 1055 0 0 0 0 0 POST / HTTP/1.1
3664 12.375 0.0034 0.0022 0.000 0.003 0.006 0.008 0.011 0.015 3664 0 0 0 2253360 615 615 615 GET /login HTTP/1.1
1825 8.192 0.0045 0.0029 0.000 0.004 0.008 0.010 0.014 0.020 0 1825 0 0 0 0 0 0 POST /register HTTP/1.1
1832 6.454 0.0035 0.0025 0.000 0.003 0.007 0.008 0.011 0.016 0 1832 0 0 43968 24 24 24 GET /logout HTTP/1.1
1471 5.422 0.0037 0.0025 0.000 0.003 0.007 0.009 0.012 0.018 0 1471 0 0 0 0 0 0 POST /comment HTTP/1.1
1825 4.237 0.0023 0.0019 0.000 0.002 0.005 0.006 0.010 0.012 0 0 1825 0 0 0 0 0 GET /admin/banned HTTP/1.1
337875 1.006 0.0000 0.0001 0.000 0.000 0.000 0.000 0.000 0.012 7692 330183 0 0 1502091683 0 4445 1265181 GET /image/$image
1 0.093 0.0930 0.0000 0.093 0.093 0.093 0.093 0.093 0.093 1 0 0 0 0 0 0 0 GET /initialize HTTP/1.1
21777 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 21776 0 0 43 0 0 43 GET /favicon.ico HTTP/1.1
21777 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 21776 0 0 1915 0 0 1915 GET /js/timeago.min.js HTTP/1.1
21777 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 21776 0 0 1549 0 0 1549 GET /css/style.css HTTP/1.1
21777 0.000 0.0000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 1 21776 0 0 1824 0 0 1824 GET /js/main.js HTTP/1.1
Nginxの負荷が目立ってきた 定番のチューニングを設定
{"pass":true,"score":542672,"success":518633,"fail":0,"messages":[]}
アプリがCPU食えば食うほどスコア上がる状態っぽいので、gzip off
{"pass":true,"score":591929,"success":567434,"fail":0,"messages":[]}
ISUCON練習会