VPS 基準測試怎麼做才準?yabs.sh、fio、sysbench、iperf3
先執行 yabs.sh 取得概略結果,再手動測試 fio、sysbench 與 iperf3。了解 CPU、記憶體、磁碟與網路數值,以及為何單次測試幾乎沒有參考價值。
VPS 基準測試的意義
VPS 基準測試會測量 4 項指標:單一 CPU 核心的執行速度、機器的記憶體頻寬、儲存裝置每秒可處理的小型隨機磁碟作業數量,以及網路連線可提供的吞吐量。執行一次 yabs.sh 約需 10 分鐘,即可取得 CPU、磁碟與網路結果;記憶體頻寬則使用下方的獨立測試。解讀結果比較困難,因為 VPS 會與其他租戶共用實體硬體。因此,同一台機器可能在 03:00 回報一個數值,在 20:00 卻回報完全不同的數值。
這裡的做法是先執行 yabs.sh 取得概略結果,再手動執行其中使用的工具。自行執行這些工具,才能變更單一 flag、觀察數值變化,並了解該數值實際測量的內容。請在機器完成設定後再進行,不要在此之前測試。請先完成新 VPS 的前 10 分鐘中的步驟,因為仍在套用第一輪更新的機器,會因與硬體無關的原因產生不準確的基準測試結果。
先了解機器,再進行測量
每個不可靠的基準測試,問題有一半在於作者不了解所使用的機器。
nproc
lscpu | grep -E 'Model name|Hypervisor|Thread'
free -h
df -hT /
uname -r
systemd-detect-virtHypervisor vendor: KVM 表示完整虛擬化,因此你會執行自己的核心。systemd-detect-virt 顯示 lxc 或 openvz 則表示容器虛擬化:你會共用主機核心,而 CPU 與記憶體限制是 cgroup(control group)設定,不是虛擬硬體。在 cgroup v2 系統上,你可以從容器的 cgroup 讀取 CPU 限制;以下路徑適用於該 cgroup 掛載在 /sys/fs/cgroup 的情況。
cat /sys/fs/cgroup/cpu.maxmax 100000 表示此 cgroup 沒有自己的配額;上層 cgroup 仍可能施加配額。200000 100000 表示你在每個 100000 微秒的週期中,可使用 200000 微秒的 CPU 時間,相當於兩個核心的配額。標示為 4 vCPU、但配額只有兩個核心的方案,基準測試結果不可能等同於四個核心。基準測試工具可以辨識這項限制:VoxelBench 會回報 CPU 配額;當主機提供的 CPU 數量遠多於伺服器可使用的數量時,也會標示 CPU 為共用或受到節流。
df -hT / 的重要性在於另一個原因:Type 欄。如果顯示 overlay,表示你位於容器內,而磁碟結果反映的是該 overlay 底層的儲存設備。現在先記下這項資訊。
持續監看 steal time
Steal time 是虛擬 CPU 在 hypervisor 未排程時,被迫等待所占的時間比例。這是 CPU 時間不可用的實用訊號,但無法區分是鄰近虛擬機負載過高,還是供應商正在套用 CPU 配額。
vmstat 1 10查看右側的 st 欄位。持續出現 steal time 表示 guest 無法取得 CPU 時間,但超過 5% 並不能證明主機過度超額配置。供應商可能會刻意將 CPU 配額限制呈現為 steal time。top 會在 CPU 列中顯示與 %st 相同的數值。執行基準測試時,請在第二個 SSH 工作階段中持續執行 vmstat 1,並將 steal 數值記錄在每項結果旁。
從 yabs.sh 開始
yabs.sh(Yet Another Bench Script)是一個 shell script,會執行 fio、iperf3 和 Geekbench,並輸出一份摘要。如果系統已安裝 fio 和 iperf3,該 script 會直接使用;如果尚未安裝,則會下載靜態 binary。yabs output 是 VPS benchmark 討論中通用的格式,因此要與他人快速比較結果時,使用 yabs 是最快的方法。
該專案提供的一行指令如下。
curl -sL yabs.sh | bash這會將該 URL 目前提供的內容直接 pipe 給 shell。請先下載並閱讀內容,再執行。
curl -sLo yabs.sh https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh
less yabs.sh
bash yabs.sh使用 pipe 時,請將 flags 放在 -s -- 之後;執行本機副本時,則直接放在檔名之後。常用選項如下:-f 略過磁碟測試,-i 略過網路測試,-g 略過 Geekbench,-r 將 iperf3 測試位置縮減為 3 個,-j 以 JSON 格式輸出結果,-w results.json 將該 JSON 寫入檔案。
bash yabs.sh -r -w yabs-run1.json首次執行前,請先了解以下 2 點。Geekbench 會上傳測試結果,並輸出公開的 browser.geekbench.com URL。任何取得該連結的人,都能查看你的 CPU 型號與分數。-g 可完全略過這項測試。其次,iperf3 階段會將實際網路流量傳送至數個區域的伺服器,這會計入每月頻寬額度。在 1 Gbit/s 連線上,完整的網路測試可能傳輸數十 GB,因此流量額度較小時請使用 -r,計量付費的連線則請使用 -i。
yabs 輸出中各部分的含義
磁碟區段會使用 fio,以 50/50 的讀取與寫入比例,測試 4k、64k、512k 和 1m 這 4 種區塊大小。每種大小都會回報 IOPS(每秒輸入/輸出作業數)和頻寬。對資料庫、郵件伺服器,或任何會執行大量小型寫入的工作負載而言,應重點查看 4k 列,因為大多數伺服器 IO 都是小型且分散的作業。1m 列則適合評估備份和影片工作負載,因為這些工作會連續搬移大量位元組。
網路區段會使用平行串流,與數個區域的公用伺服器執行 iperf3 測試,並測量兩個方向。低數值應視為需要調查的問題,而不是確定的結論,因為公用 iperf3 伺服器由多人共用,且經常已達飽和。因此,結果不佳可能是遠端端點造成的。
Geekbench 區段會提供單核心分數和多核心分數。單核心分數可預測單一要求、單次編譯或單一查詢完成的速度。多核心分數主要表示你實際取得了多少個核心。
磁碟:自行執行 fio
fio(flexible IO tester)是 yabs 磁碟測試區段底層使用的工具,直接執行它才能了解各個旗標的實際意義。
sudo apt update && sudo apt install -y fio sysbench iperf3在你實際關心的檔案系統上,以佇列深度 32 執行 4k 隨機讀取測試:
fio --name=randread4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randread --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reporting輸出中需要讀取的摘要列如下。
read: IOPS=184k, BW=719MiB/s (754MB/s)(42.1GiB/60001msec)fio 會在下方輸出一個 clat percentiles 區塊。值得引用的是第 99.00 百分位數,因為它表示每 100 個請求中,最慢的 1 個請求等待了多久。平均延遲會掩蓋使用者實際感受到的停頓。
--direct=1使用O_DIRECT開啟檔案,因此讀取會繞過 kernel page cache。若未使用此旗標,在擁有 8G RAM 的機器上,第二次讀取 2G 檔案時會直接由記憶體提供資料,fio 回報的 IOPS 會達到數百萬。這個數字是真實的,但反映的是記憶體效能。--ioengine=libaio提交非同步請求,因此--iodepth=32能讓 32 個請求同時處於處理中。使用psync這類同步引擎時,超過 1 的 iodepth 完全不會產生作用,因此測量的是一次一個請求。--time_based --runtime=60會固定執行 60 秒,而不是固定執行某個工作量,因此快速磁碟與慢速磁碟會使用相同的實際經過時間,比較結果較為公平。--size=2G設定測試檔案大小。請讓它大於整條路徑上的任何快取,並先確認有足夠的可用空間。
隨機寫入使用相同的命令,搭配 --rw=randwrite。請分開執行,然後刪除檔案。
fio --name=randwrite4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randwrite --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reporting
rm -f ./fio-testfile若要使用更接近實際網路流量的混合模式,請使用 --rw=randrw --rwmixread=70。你使用的儲存裝置類型對結果的影響,大於任何旗標;這項差異詳見 VPS 上 NVMe 與 SATA SSD 儲存空間的差異。
fio 停止並顯示 Unknown error -1
並非所有檔案系統都支援直接 I/O,因此 fio 在啟用 --direct=1 時,若第一個要求就失敗,應先排除直接 I/O。錯誤可能如下所示:
fio: io_u error on file ./fio-testfile: Unknown error -1: read offset=0, buflen=4096
fio: pid=1234, err=-1/file:ioengines.c:321, func=get_events, error=Unknown error -1先執行 df -hT .。Type 是 overlay,也就是 Docker 預設提供給容器的檔案系統;單獨使用它並不會造成問題。overlayfs 會將 O_DIRECT 傳遞給底層檔案系統,只有在底層檔案系統不支援直接 I/O 時才會拒絕,因此位於 ext4 或 xfs 之上的 overlay 可正常使用 --direct=1 --ioengine=libaio。若測試檔案所在的底層檔案系統確實不支援直接 I/O,fio 通常會在開啟檔案時指出原因:fio: looks like your file system does not support direct=1/buffered=0。此時請將 --filename 指向真實本機儲存空間中的路徑,例如 bind mount 的 volume;或者改在 host 上執行 fio,而不要在容器內執行。若無法存取真實儲存空間,至少可以執行緩衝同步測試,以確認指令本身正確。
fio --name=randread4k-buffered --filename=./fio-testfile --size=256M --bs=4k \
--rw=randread --ioengine=psync --direct=0 --numjobs=1 \
--runtime=15 --time_based --group_reporting
rm -f ./fio-testfile請如實說明這項測試的意義。第一次測試後,256M 檔案會留在 page cache 中,因此 IOPS 數值反映的是 RAM 的效能。可用它確認 fio 已安裝且能正確解析 flags。不要將這個數值引用為磁碟效能結果。
為什麼 dd 不是磁碟基準測試
dd 常見於許多 VPS 討論串,能回答一個範圍很窄的問題。
dd if=/dev/zero of=./ddtest bs=1M count=1024 oflag=direct conv=fdatasync
rm -f ./ddtest這會測量單一執行緒、單一未完成請求下的循序寫入吞吐量。這是合理的基本檢查,但無法反映隨機 IO,也無法說明同時到達 32 個請求時的情況。移除 oflag=direct 後,寫入會經過 page cache;但 conv=fdatasync 仍會在命令完成前,強制將輸出資料寫入儲存裝置。連這個選項也移除後,結果主要可能只是在測量 kernel 將寫入資料接受至記憶體的速度。因此,論壇文章中引用的 dd 數值經常荒謬地偏高。
CPU:sysbench cpu
sysbench cpu --cpu-max-prime=20000 --threads=1 run
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) run應保留的數值是 events per second。先執行單執行緒測試。這個數值會影響單一 PHP 請求完成或單一編譯工作完成的速度,而且在價格相同的主機之間差異最大。接著使用所有執行緒測試,觀察處理量如何隨配置給你的 vCPU 數量擴展。
請明確了解這項測試測量的內容:sysbench cpu 會透過試除法反覆找出質數。對每個候選數值,測試會先計算 double precision 平方根,再使用 64 位元整數取模運算測試除數,並將每個除數與這個浮點數上限比較。因此,它同時包含整數與浮點數運算。這項測試不會以接近實際工作負載的方式測試記憶體頻寬、向量運算單元或快取。因此,它適合用來比較兩台主機,但不適合預測應用程式的實際執行表現。
Ubuntu 24.04 隨附 sysbench 1.0.20,測試名稱會放在前面。若從舊文章複製含有 --test=cpu 的命令,會得到 WARNING: the --test option is deprecated。sysbench 0.4 與 sysbench 1.0 的分數完全不可比較,因此不要拿自己的結果與未標明版本的公開數值比較。
記憶體:sysbench 記憶體
sysbench memory --memory-block-size=1M --memory-total-size=20G --memory-oper=write --threads=1 run
sysbench memory --memory-block-size=1M --memory-total-size=20G --memory-oper=read --threads=1 run結果的單位是 MiB/sec。將 --memory-block-size 固定為 1M,並確保所有比較的主機都使用完全相同的設定。在 1K 下,數值會大幅下降,因為每次操作的額外成本增加了 1000 倍,最後測量到的是迴圈成本,而不是記憶體頻寬。這是已發布的記憶體效能分數中最常見的不一致旗標。
網路:iperf3
測試吞吐量的正確方式,是對你所控制的另一台機器進行測試。這樣你才能知道兩端正在執行的工作。
在遠端:
iperf3 -s這會在 TCP 5201 上監聽。僅允許測試來源的位址連線至此連接埠,完成後立即關閉。VPS 上的基本 ufw 防火牆規則說明相關語法。
從受測試的 VPS 執行:
iperf3 -c 203.0.113.10 -t 30
iperf3 -c 203.0.113.10 -t 30 -R
iperf3 -c 203.0.113.10 -t 30 -P 8第一個指令會測量受測機器的上傳速度。-R 會反轉傳輸方向,因此測量下載速度。-P 8 會開啟 8 個平行資料流。
請同時執行單一資料流版本和平行版本,因為兩者回答的問題不同。單一 TCP 連線能承載的未確認資料量,最多取決於其視窗大小。因此,其上限大致等於視窗大小除以往返時間。延遲為 80 ms、視窗大小為 4 MB 時,即使底層連線速度更快,上限也約為 400 Mbit/s。單一資料流的數值表示一次下載可取得的速度。平行資料流的數值表示連線的容量。
執行測試時,請留意頻寬用量上限。以 1 Gbit/s 傳輸 30 秒約會傳送 3.75 GB,而且你會在每個方向執行數次。
參考數據,以及如何解讀您的結果
此圖表背後的資料
[
{
"device": "Local NVMe",
"iops_4k_read": "180,000"
},
{
"device": "Local SATA SSD",
"iops_4k_read": "90,000"
},
{
"device": "Network block",
"iops_4k_read": "12,000"
},
{
"device": "Spinning disk",
"iops_4k_read": "180"
}
]公開測試結果中,本機 NVMe 卷通常約為 180,000 4k 隨機讀取 IOPS。本機 SATA SSD 約為 90,000。網路連線的區塊儲存每次請求都必須先經過網路才能到達磁碟,通常約為 12,000;傳統旋轉式磁碟則約為 180,因為每次隨機請求都需要移動實體磁頭。
這些是各類儲存裝置常見的公開數據,不是單一主機的測量結果。請只將它們用於確認您自己的結果是否落在相同數量級。如果標示為 NVMe 的方案測得的結果只有數千 4k IOPS,請先確認 --direct=1 是否已啟用。若已啟用,請檢查該方案的 IOPS 限制與突發額度,以及儲存資源競爭和宣稱提供的硬體。
為什麼執行一次不能算是基準測試
單次結果只是共用機器在某 1 分鐘內的快照。應將它視為一個樣本。
- 每項測試至少執行五次,分散在不同時段,且至少跨越兩天。保留中位數與分布範圍。發布結果時未提供分布範圍,就只是行銷數字。
- 在每次測試旁記錄 steal time。保留
st偏高的測試,並調查這些結果反映的是資源競爭,還是方案的 CPU 配額;直接捨棄這些結果,可能掩蓋你實際取得的效能。 - 以兩種持續時間執行磁碟測試。許多方案提供會隨時間補充的突發 IOPS 額度,但無論是 60 秒的 fio 測試,還是
--runtime=600,都不能保證測得的是效能下限。AWS gp2 在額度充足時,至少可維持 3,000 IOPS 30 分鐘,因此兩次測試都可能測到突發效能。在將結果視為持續效能前,請確認供應商的額度機制,並監控額度餘額。 - 確認沒有其他工作正在執行。
unattended-upgrades在 CPU 測試中途啟動 apt 交易,會實際拉低測試分數;而且每次測試前執行ps -e -o comm= | grep -E 'apt|dpkg'只需 1 秒。 - 一次只變更一個變數。不同的工具版本、區塊大小或執行緒數會產生無法比較的數字,無論結果看起來多麼相近。
比較兩家供應商時,請在同一天的相同時段執行測試。否則測到的其實是時段差異。
最後再對自己的工作負載進行基準測試
合成測試工具可以對機器排名。只有自己的工作負載能告訴你機器是否足夠。請測量你實際執行的工作所需時間。
time tar -czf /tmp/bench.tgz /usr/share
rm -f /tmp/bench.tgz這會壓縮幾百 MB 的資料,因此會同時測試 CPU 和磁碟;任一者變動,結果都會跟著變化。出現 Removing leading / from member names 警告是正常的。更好的做法是測量自己的建置、最慢的查詢,或頁面呈現時間。某個主機的建置需要 4 分鐘,另一個主機需要 7 分鐘;無論 Geekbench 的結果為何,這已經回答了問題。這項測量也能告訴你,升級機器何時不再值得付費。這點很重要,因為你可能會先閱讀VPS 每月實際費用,或將工作負載移至專用伺服器。
FAQ
為什麼每次執行基準測試時,結果都不一樣?
VPS 會與其他租戶共用實體 CPU、儲存裝置與網路,因此結果取決於當下其他租戶正在執行的工作。測試期間執行 vmstat 1,並查看 st 欄位:持續的 steal time 會記錄無法使用的 CPU 時間,但這可能反映供應商正在限制你購買的 CPU 配額,也可能是主機資源競爭所致。數值高於 5% 並不能確定原因。正確做法是改善測試方法,而不是調校系統。在不同時段各執行測試 5 次以上,然後回報中位數及分布範圍。
為什麼 fio 會回報數百萬 IOPS?
幾乎都是因為缺少 --direct=1。沒有這個選項時,fio 會透過 kernel page cache 讀取,因此第一次執行後,2G 測試檔會由 RAM 提供資料,實際測量到的是記憶體頻寬。加入 --direct=1,並讓測試檔大於路徑上的任何快取。若 --direct=1 接著失敗,執行 df -hT .,確認測試檔實際位於哪種儲存裝置上。overlay 類型本身不是問題,因為 overlayfs 會將 O_DIRECT 傳遞到底層儲存裝置。只有在底層檔案系統拒絕 direct IO 時,才需要將測試檔移至實體本機儲存裝置。
yabs.sh 單獨使用是否足夠?
作為初步檢查,足夠。它會以 4 種 block size 執行 fio,讓 iperf3 雙向測試,並執行 Geekbench,最後輸出一份其他人也能閱讀的摘要。當你想了解某個數值為何如此時,它就不夠用了,因為你無法針對各項測試調整其 flags。yabs 結果看起來不合理時,請直接使用 fio 或 sysbench 重現測試,並一次只變更 1 個 flag。
哪一個單一數值最能預測應用程式的實際使用感受?
對多數 Web 與資料庫工作負載而言,依重要性排序,通常是單核心 CPU 速度,其次是 4k 隨機讀取延遲。吞吐量數值看起來很高,但很少能決定實際表現,因為一般請求的資料量通常很小。請引用 fio clat percentiles 區塊的 99 百分位數,而不是平均值,因為每 100 個請求中最慢的那 1 個,才是使用者會察覺的延遲。
執行基準測試前需要安裝任何套件嗎?
fio、sysbench 和 iperf3 都包含在 Ubuntu 與 Debian 的套件庫中:sudo apt install -y fio sysbench iperf3。yabs.sh 會在 Bash 中執行;下載檔案需要 curl 或 wget,擷取 Geekbench 則需要 tar。沒有 tar 時,會略過 Geekbench。若系統已安裝 fio 和 iperf3,便會直接使用;缺少時則會下載靜態二進位檔。完成後請刪除所有測試檔,因為留在 20G 磁碟上的 2G fio 檔案,數週後可能會成為磁碟已滿告警的原因。