Skip to content

[Linux] 使用命令列測試硬碟讀寫速度

Last Updated on 2024-08-08 by Clay

當我們買了一顆新硬碟、或是評估是否要啟用一顆硬碟時,該硬體的讀寫速度肯定是我們最在意的,畢竟這非常直接地影響了我們之後使用這顆硬碟的使用體驗。

以我為例,我想要在外接硬碟上多裝一個作業系統,所以想要先評估一下外接硬碟的效果、再來決定是否要繼續往下做。而評估的方式,我們主要可以透過 ddhdparmfio 等指令來進行。

如果你不想要額外安裝工具,可以直接使用系統原生的 dd 指令;如果你願意安裝一個新的工具,但又不想配置太多設定,那麼首推絕對是 hdparm;但如果你不介意安裝新工具或配置設定檔,只想要看到最詳盡的結果,那 fio 會比前兩者來得更適合你。

總之,首先我們先來用 lsblk 確認硬碟吧!個人習慣上我會推薦把 loop 隱藏掉比較方便閱讀。

lsblk | grep -v loop


Output:

NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 931.5G 0 disk
└─sda1 8:1 0 931.5G 0 part /media/clay/CLAY_DEVICE
nvme0n1 259:0 0 953.9G 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot/efi
└─nvme0n1p2 259:2 0 953.4G 0 part /var/snap/firefox/common/host-hunspell
/


sda 是我的外接的 HDD,我由系統自動掛載在 /media/clay/CLAY_DEVICE 這個資料夾底下,nvme0n1 則是我筆電上內建的 SSD。


dd 指令

我們可以使用 dd 直接寫一個 1G 的檔案進去想要測試的硬碟,順帶打印出時間。

sync; dd if=/dev/zero of=/media/clay/CLAY_DEVICE/testfile bs=1G count=1 oflag=direct; sync


Output:

1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 25.1677 s, 42.7 MB/s


反過來,我們也可以從放到硬碟的 testfile 測試讀取 1GB 的資料速度來測試讀取。

sync; dd if=/media/clay/CLAY_DEVICE/testfile of=/dev/null bs=1G count=1 iflag=direct; sync


Output:

1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 24.4449 s, 43.9 MB/s


這個方法最單純直接,並且不需要安裝其他工具;但是要小心不要亂寫入文件,不小心寫到重要資訊是很可怕的。


hdparm 指令

首先我們可以先安裝這個工具:

sudo apt install hdparm


之後,直接下:

sudo hdparm -tT /dev/sda


Output:

/dev/sda:
Timing cached reads: 35514 MB in 2.00 seconds = 17784.75 MB/sec
Timing buffered disk reads: 124 MB in 3.00 seconds = 41.32 MB/sec


其中 -T 是從暫存中讀取的速度,而 -t 是測試從硬碟直接讀取的速度,所以才會兩個都顯示出來。


fio 指令

首先我們同樣先安裝 fio 指令:

sudo apt install fio


之後,我們需要先配置一個設定檔:

[global]
size=1G
direct=1
ioengine=libaio
bs=4k
numjobs=1
runtime=60
group_reporting

[readtest]
rw=read
filename=/media/clay/CLAY_DEVICE/readtestfile

[writetest]
rw=write
filename=/media/clay/CLAY_DEVICE/writetestfile


接著就可以使用以下指令來跑 fio 分析了。

fio fiotest.fio


Output:

readtest: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=1
writetest: (g=0): rw=write, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=1
fio-3.28
Starting 2 processes
readtest: Laying out IO file (1 file / 1024MiB)
writetest: Laying out IO file (1 file / 1024MiB)
Jobs: 2 (f=0): [f(2)][100.0%][r=984KiB/s,w=984KiB/s][r=246,w=246 IOPS][eta 00m:00s]
readtest: (groupid=0, jobs=2): err= 0: pid=2945986: Thu Aug 8 16:05:06 2024
read: IOPS=1203, BW=4815KiB/s (4931kB/s)(282MiB/60002msec)
slat (usec): min=3, max=218, avg=10.08, stdev= 8.82
clat (usec): min=209, max=87275, avg=819.46, stdev=1644.63
lat (usec): min=248, max=87283, avg=829.62, stdev=1645.49
clat percentiles (usec):
| 1.00th=[ 285], 5.00th=[ 314], 10.00th=[ 322], 20.00th=[ 347],
| 30.00th=[ 359], 40.00th=[ 367], 50.00th=[ 375], 60.00th=[ 396],
| 70.00th=[ 445], 80.00th=[ 482], 90.00th=[ 3687], 95.00th=[ 3916],
| 99.00th=[ 4228], 99.50th=[ 4490], 99.90th=[11469], 99.95th=[17433],
| 99.99th=[55837]
bw ( KiB/s): min= 856, max= 9947, per=100.00%, avg=4848.71, stdev=3366.90, samples=119
iops : min= 214, max= 2486, avg=1212.14, stdev=841.71, samples=119
write: IOPS=1248, BW=4996KiB/s (5116kB/s)(293MiB/60001msec); 0 zone resets
slat (usec): min=242, max=82627, avg=798.46, stdev=1525.30
clat (nsec): min=166, max=41292, avg=975.41, stdev=1372.50
lat (usec): min=242, max=82638, avg=799.75, stdev=1525.55
clat percentiles (nsec):
| 1.00th=[ 193], 5.00th=[ 213], 10.00th=[ 219], 20.00th=[ 249],
| 30.00th=[ 258], 40.00th=[ 266], 50.00th=[ 294], 60.00th=[ 426],
| 70.00th=[ 652], 80.00th=[ 2040], 90.00th=[ 2672], 95.00th=[ 4384],
| 99.00th=[ 4960], 99.50th=[ 5344], 99.90th=[14272], 99.95th=[15168],
| 99.99th=[23680]
bw ( KiB/s): min= 863, max=10288, per=100.00%, avg=5030.72, stdev=3491.87, samples=119
iops : min= 215, max= 2572, avg=1257.65, stdev=872.96, samples=119
lat (nsec) : 250=10.39%, 500=21.31%, 750=4.99%, 1000=1.54%
lat (usec) : 2=2.41%, 4=7.23%, 10=2.97%, 20=0.07%, 50=0.01%
lat (usec) : 250=0.01%, 500=41.67%, 750=1.86%, 1000=0.08%
lat (msec) : 2=0.02%, 4=4.03%, 10=1.34%, 20=0.05%, 50=0.01%
lat (msec) : 100=0.01%
cpu : usr=0.25%, sys=2.13%, ctx=147417, majf=0, minf=28
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=72234,74941,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
READ: bw=4815KiB/s (4931kB/s), 4815KiB/s-4815KiB/s (4931kB/s-4931kB/s), io=282MiB (296MB), run=60002-60002msec
WRITE: bw=4996KiB/s (5116kB/s), 4996KiB/s-4996KiB/s (5116kB/s-5116kB/s), io=293MiB (307MB), run=60001-60001msec

Disk stats (read/write):
sda: ios=72177/74894, merge=0/1, ticks=58993/58467, in_queue=117458, util=99.88%


以下是 fio 配置文件的簡單解釋:

[global] 段

這段定義了所有測試共用的全域設定:

  1. size=1G
    這個參數指定每個工作(job)讀寫的總資料大小為 1GB
  2. direct=1
    設定為 1 表示進行直接 I/O 操作,不使用作業系統的暫存
  3. ioengine=libaio
    指定 I/O 引擎為 libaio,即 Linux 的異步 I/O 引擎。這是 fio 支持的多種 I/O 引擎之一,適合進行高效的異步 I/O 操作
  4. bs=4k
    指定 I/O 操作的塊大小為 4KB,這是每次讀寫操作的資料區塊大小
  5. numjobs=1
    指定啟動的工作數量(jobs)為 1,這意味著在這個測試中只有一個併發操作
  6. runtime=60
    指定測試運行的時間為 60 秒,測試將持續這段時間,不管是否達到指定的資料大小
  7. group_reporting
    啟用群組報告模式,將所有工作的結果彙總在一起報告,而不是分別報告。

[readtest] 段

這段定義了專門針對讀取測試的設置:

  1. rw=read
    指定 I/O 操作為讀取(read),這意味著這個工作只會進行讀取操作
  2. filename=/media/clay/CLAY_DEVICE/readtestfile
    指定要讀取的文件為 /media/clay/CLAY_DEVICE/readtestfile

[writetest] 段

這段定義了專門針對寫入測試的設置:

  1. rw=write
    指定 I/O 操作為寫入(write),這意味著這個工作只會進行寫入操作
  2. filename=/media/clay/CLAY_DEVICE/writetestfile
    指定要寫入的文件為 /media/clay/CLAY_DEVICE/writetestfile

結語

我使用了以上三種工具分析了我的 HDD,發現果然差 SSD 不少,最後還是放棄了用 HDD 當作我的另外一個緊急備用作業系統。


References


Read More

Tags:

Leave a Reply取消回覆

Exit mobile version