伺服器好慢啊~ 總之來測試一下吧 – I/O 測試
先說好,我不敢保證這個系列會繼續下去喔!(我個人實在相當希望能快點完結)
這個系列紀錄的是我嘗試改善效能的各種嘗試,大概試到一個程度,我感覺滿意了就會停了。
前情提要
目前本站的網站伺服器是跑在一片 Raspberry Pi4 (4GB) 上,但是效能實在是太差了,光載入首頁可能就要讓使用者等 2 秒以上…
總之先上 Spec:
- 64 位元 ARM 架構四核心 @1.5GHz(Broadcom BCM2711, Quad core Cortex-A72)
- 4GB LPDDR4-3200 SDRAM
- Gigabit Ethernet
看到這樣的規格,你會猜測,或許是記憶體不夠吧?
$ free -h
total used free shared buff/cache available
Mem: 3.7Gi 1.3Gi 218Mi 124Mi 2.2Gi 2.2Gi
Swap: 0B 0B 0B
▲ 很可惜的,似乎完全不是這麼一回事。
$ uptime
04:40:58 up 16 days, 4:35, 1 user, load average: 0.32, 1.94, 1.79
▲ CPU 的負載也看不出什麼問題…
$ iostat
Linux 5.4.0-1029-raspi (Play-PC-Pi8) 2021年03月16日 _aarch64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.35 0.01 0.34 1.37 0.00 97.94
▲ %iowait
可能多了一點?!
使用 hdparm
測試讀取效能
安裝:
sudo apt install hdparm
非常多功能的簡易測試工具,名稱來自 Hard Drive Parameters(硬碟參數)的縮寫。
$ sudo hdparm -I /dev/sda
/dev/sda:
ATA device, with non-removable media
Model Number: CT500MX500SSD1
Serial Number: 2022E2A74CBE
Firmware Revision: M3CR023
Transport: Serial, ATA8-AST, SATA 1.0a, SATA II Extensions, SATA Rev 2.5, SATA Rev 2.6, SATA Rev 3.0
Standards:
Used: unknown (minor revision code 0x006d)
Supported: 10 9 8 7 6 5
Likely used: 10
...略...
可以使用 -I
顯示硬碟資訊,如果是記憶卡的話可能沒辦法顯示
$ sudo hdparm -t /dev/sda
/dev/sda:
Timing buffered disk reads: 324 MB in 3.01 seconds = 107.75 MB/sec
使用 -t
可以測試硬碟的讀取效能,除此之外,也可以試試底下的幾種參數:
-t
: 測試硬碟讀取效能,會依據硬碟大小自動決定測試的大小-T
: 測試硬碟 快取 讀取效能--direct
: 測試 raw I/O 的讀取效能(跳過作業系統的分頁機制)
對記憶卡紀行測試的時候,會顯示
HDIO_DRIVE_CMD
訊息,這是正常的$ sudo hdparm -t /dev/mmcblk0 /dev/mmcblk0: HDIO_DRIVE_CMD(identify) failed: Invalid argument Timing buffered disk reads: 130 MB in 3.03 seconds = 42.93 MB/sec
原因是 hdparm 在測試之前會先透過 ATA 界面,試圖判斷目標裝置的容量(
-I
)的緣故
使用 fio
進行更加詳細(危險)的測試
全名 flexible I/O tester,這個程式可以測試的項目相當廣泛,因為真的太廣泛了,我想先用兩個範例(模仿 CrystalDiskMark)來解釋一下
安裝:
sudo apt install fio
RAND 4K Q1T1:
fio \
--filename=fio_test \
--size=1G \
--rw=randrw \
--bs=4k \
--name=fio_test
RAND 4K Q32T16:
fio \
--filename=fio_test \
--size=1G \
--rw=randrw \
--bs=4k \
--iodepth=32 \
--numjobs=16 \
--thread \
--group_reporting \
--name=fio_test
讓我們解釋一下幾個我個人覺得有趣的選項:
--filename
: 可以隨意取名,也可以使用/dev/sda
等區塊裝置名稱(會抹除區塊裝置內的資料)--size
: 測試檔案的大小--readwrite
/--rw
: 讀寫模式read
: 循序讀取write
: 循序寫入trim
: 循序 TRIM 命令- 加上
rand
可以從循序變成隨機模式(e.g.randread
) randrw
: 隨機讀寫trimwrite
: 循序 trim+write 命令
--bs
: 區塊大小,以 byte 為單位,也可以使用 k 代表 1024(e.g. 4k 代表 4096 byte)--iodepth
: 同一時間允許多少存取--numjobs
: 同時開啟的工作數量(aka 複製自己)--thread
: fio 預設使用 process(fork) 平行處理,我們可以選擇使用 thread--group_reporting
: 可以把多個工作的結果整合成一個報告,只有numjobs > 1
時才有意義--name
: 工作(測試)名稱,可以隨意取名,我們使用這個選項只是讓我們進入命令列模式(CLI),跳過編寫 jobfile 的麻煩
記得刪掉測試檔案:
rm fio_test
範例輸出:
$ fio \
--filename=fio_test \
--size=1G \
--rw=randrw \
--bs=4k \
--iodepth=32 \
--numjobs=16 \
--thread \
--group_reporting \
--name=fio_test
fio_test: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=32
...
fio-3.16
Starting 16 threads
Jobs: 1 (f=1): [_(13),m(1),_(2)][99.0%][r=11.6MiB/s,w=11.3MiB/s][r=2973,w=2900 IOPS][eta 00m:14s]
fio_test: (groupid=0, jobs=16): err= 0: pid=2817936: Wed Mar 17 05:14:28 2021
read: IOPS=1470, BW=5882KiB/s (6023kB/s)(8185MiB/1424847msec)
clat (usec): min=4, max=12828k, avg=1611.91, stdev=50194.59
lat (usec): min=4, max=12828k, avg=1612.34, stdev=50194.59
clat percentiles (usec):
| 1.00th=[ 6], 5.00th=[ 7], 10.00th=[ 7],
| 20.00th=[ 8], 30.00th=[ 9], 40.00th=[ 10],
| 50.00th=[ 12], 60.00th=[ 13], 70.00th=[ 14],
| 80.00th=[ 15], 90.00th=[ 17], 95.00th=[ 3621],
| 99.00th=[ 25822], 99.50th=[ 29754], 99.90th=[ 62653],
| 99.95th=[ 534774], 99.99th=[1350566]
bw ( KiB/s): min= 115, max=148448, per=100.00%, avg=13649.80, stdev=877.21, samples=19580
iops : min= 19, max=37112, avg=3411.77, stdev=219.31, samples=19580
write: IOPS=1473, BW=5892KiB/s (6034kB/s)(8199MiB/1424847msec); 0 zone resets
clat (usec): min=10, max=13410k, avg=8363.59, stdev=170561.30
lat (usec): min=10, max=13410k, avg=8364.16, stdev=170561.42
clat percentiles (usec):
| 1.00th=[ 14], 5.00th=[ 16], 10.00th=[ 20],
| 20.00th=[ 25], 30.00th=[ 30], 40.00th=[ 33],
| 50.00th=[ 39], 60.00th=[ 44], 70.00th=[ 53],
| 80.00th=[ 63], 90.00th=[ 76], 95.00th=[ 90],
| 99.00th=[ 139461], 99.50th=[ 252707], 99.90th=[1266680],
| 99.95th=[5268046], 99.99th=[6341788]
bw ( KiB/s): min= 116, max=148800, per=100.00%, avg=13699.90, stdev=876.60, samples=19542
iops : min= 20, max=37200, avg=3424.29, stdev=219.16, samples=19542
lat (usec) : 10=20.25%, 20=31.16%, 50=28.92%, 100=14.83%, 250=0.55%
lat (usec) : 500=0.05%, 750=0.02%, 1000=0.01%
lat (msec) : 2=0.24%, 4=0.59%, 10=1.28%, 20=0.48%, 50=0.76%
lat (msec) : 100=0.14%, 250=0.44%, 500=0.17%, 750=0.03%, 1000=0.02%
lat (msec) : 2000=0.01%, >=2000=0.05%
cpu : usr=0.11%, sys=0.53%, ctx=416597, majf=0, minf=0
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=2095332,2098972,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32
Run status group 0 (all jobs):
READ: bw=5882KiB/s (6023kB/s), 5882KiB/s-5882KiB/s (6023kB/s-6023kB/s), io=8185MiB (8582MB), run=1424847-1424847msec
WRITE: bw=5892KiB/s (6034kB/s), 5892KiB/s-5892KiB/s (6034kB/s-6034kB/s), io=8199MiB (8597MB), run=1424847-1424847msec
Disk stats (read/write):
mmcblk0: ios=131062/633321, merge=21/8740, ticks=2653177/72797058, in_queue=73915748, util=99.08%
補充:如何決定 bs
(block size)數值?
我建議可以先從裝置的原生磁區大小開始,可以使用 fdisk
指令取得資訊
~ » sudo fdisk -l /dev/sda
Disk /dev/sda: 465.8 GiB, 500107862016 bytes, 976773168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: DA7FC779-1AB7-44B3-AB5D-E68C99836A1C
可以看出這個硬碟是 4K 格式(AF)
使用 sysbench
有鑑於上面的結果,我猜測 DB 的存取速度,應該是一大問題… 不過我們還可以使用這個工具來進行 DB 效能的測試
(咳)總之,sysbench
能夠測試系統的 CPU、記憶體、I/O 等多個面向,可以說是相當方便的工具。
安裝:
sudo apt install sysbench
簡單的磁碟效能測試:
# 建立測試檔案
sysbench fileio --file-test-mode=rndrw prepare
# 進行測試
sysbench fileio --file-test-mode=rndrw run
# 清除測試檔案
sysbench fileio --file-test-mode=rndrw cleanup
重點是 DB(MySQL)效能測試!!
因為 Ubuntu 官方打包的版本有時比較舊,請自行確認測試設定檔的名稱
$ ls /usr/share/sysbench
bulk_insert.lua oltp_point_select.lua oltp_update_non_index.lua
oltp_common.lua oltp_read_only.lua oltp_write_only.lua
oltp_delete.lua oltp_read_write.lua select_random_points.lua
oltp_insert.lua oltp_update_index.lua select_random_ranges.lua
我們要找的是 OLTP(線上交易處理)開頭的設定檔。
注:如果真的找不到,也可以至 sysbench 的官方 GitHub 下載編譯,照著指令複製貼上即可: akopytov/sysbench: Scriptable database and system performance benchmark
另外,為了避免更動到資料庫裡面既有的資料,必須先建立一個空資料庫(sbtest
)
(請依照自己的環境操作,以下指令僅供參考)
安裝 MariaDB 10.5:
# 設定軟體來源
sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
sudo add-apt-repository 'deb [arch=amd64,arm64] https://ftp.ubuntu-tw.org/mirror/mariadb/repo/10.5/ubuntu focal main'
# 安裝
sudo apt install mariadb-server
# 初始化(unix_socket authentication,允許已登入主機的同名的使用者,直接登入)
sudo mariadb-secure-installation
登入 root
帳戶:
mariadb -u root -p
建立資料庫(sbtest
)與使用者(sbtest
,不用密碼):
CREATE DATABASE sbtest;
CREATE USER 'sbtest'@'localhost';
GRANT ALL PRIVILEGES ON * . * TO 'sbtest'@'localhost';
FLUSH PRIVILEGES;
quit;
這邊選擇的是 oltp_read_write.lua
這個測試(不須指定副檔名,除非你的測試檔案不在預設路徑 /usr/share/sysbench
):
sysbench oltp_read_write --db-driver=mysql prepare
sysbench oltp_read_write --db-driver=mysql run
sysbench oltp_read_write --db-driver=mysql cleanup
刪除測試資料庫(sbtest
)與使用者(sbtest
):
SELECT User,Host FROM mysql.user;
DROP USER 'sbtest'@'localhost';
SHOW DATABASES;
DROP DATABASE sbtest;
FLUSH PRIVILEGES;
quit;
範例輸出:
$ sysbench oltp_read_write --db-driver=mysql run
sysbench 1.0.18 (using system LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 1
Initializing random number generator from current time
Initializing worker threads...
Threads started!
SQL statistics:
queries performed:
read: 7336
write: 2096
other: 1048
total: 10480
transactions: 524 (51.09 per sec.)
queries: 10480 (1021.75 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 10.2477s
total number of events: 524
Latency (ms):
min: 7.46
avg: 19.54
max: 727.57
95th percentile: 17.32
sum: 10238.47
Threads fairness:
events (avg/stddev): 524.0000/0.00
execution time (avg/stddev): 10.2385/0.00
似乎沒什麼問題,看來是需要更多的測試,敬請期待(淚)
參考資料
hdparm
相關- Linux command – hdparm – Benjr.tw
- 提到了
hdparm
哪些參數可以用來進行效能測試
- 提到了
- Ubuntu Manpage: hdparm – get/set SATA/IDE device parameters
- Ubuntu 官方文件庫,詳細的解釋了
hdparm
每個參數的使用時機
- Ubuntu 官方文件庫,詳細的解釋了
- hdparm, HDIO_DRIVE_CMD(identify) failed: Invalid argument – Raspberry Pi Forums
- Raspberry Pi 論壇,感謝
trejan
(使用者) 解釋HDIO_DRIVE_CMD
的原因
- Raspberry Pi 論壇,感謝
- Linux command – hdparm – Benjr.tw
fio
相關- Fio 效能測試 – Benjr.tw
- 提到了
fio
哪些參數可以用來進行效能測試
- 提到了
- Ubuntu Manpage: fio – flexible I/O tester
- Ubuntu 官方文件庫,詳細的解釋了
fio
每個參數的使用時機
- Ubuntu 官方文件庫,詳細的解釋了
- Fio 效能測試 – Benjr.tw
marisdb-server
相關- MariaDB – Setting up MariaDB Repositories – MariaDB
- MariaDB 官方的套件來源
- How To Install MariaDB on Ubuntu 20.04 | DigitalOcean
- 可靠的教學,詳細的解釋了安裝 MariaDB 的每個步驟
- Authentication Plugin – Unix Socket – MariaDB Knowledge Base
- MariaDB 官方的知識庫,解釋
unix_socket authentication
是什麼東西
- MariaDB 官方的知識庫,解釋
- MariaDB – Setting up MariaDB Repositories – MariaDB
sysbench
相關- Ubuntu Manpage: sysbench – multi-threaded benchmark tool for database systems
- Ubuntu 官方文件庫,確認了預設套件來源確實比較舊 Orz
- akopytov/sysbench: Scriptable database and system performance benchmark
- 簡單介紹了如何編譯最新版本,和基本的使用方法
- Ubuntu Manpage: sysbench – multi-threaded benchmark tool for database systems