HDD test
Тест жестких дисков (и других блочных устройств)
Линейное чтение
Линейное чтение (с заданным шагом). Да, я знаю что это весьма косвенный показатель. Но куда ж без него.
Не забыть iflag=direct
Значения count и step подбирать по желанию - насколько усреднять.
Естественно читать чаще чем нужно смысла нет, а вот для больших дисков несколько интерполировать.
Скрипт для сбора статистики
#!/bin/bash step=2048 i=1 device=sda while A=`dd iflag=direct if=/dev/${device} of=/dev/null skip=$[${step}*${i}]k bs=8k count=256k 2>&1` do B=`echo $A | grep "bytes" | awk ' {print $14" "$15} '` echo $[${step}*${i}]" "$B echo $[${step}*${i}]" "$B | sed s/','/'.'/g >> line_read.${device} let i=i+1 done
Построенеи графиков
Далее строим график GnuPlot, что то вроде такого:
#!/usr/bin/gnuplot -persist set terminal png size 1600,800 set output "master_Line_Read_Speed_sdi.png" set ylabel "Speed, MB/s" set xlabel "Offset" set grid plot \ "result_sdi" using 1:2 with linespoints lt rgb "blue" lw 2 title "Line Read"
Разброс есть, но вцелом похоже на правду.
Можно попробовать сглаживание:
plot \ "result_sda" using 1:2 smooth bezier lw 2 title "Line Read sda", \
Многопоточность
Есть замечательная утилита - fio для работы с которой я написал небольшую обвязку
Скрипт для сбора статистики
Для каждой глубины очереди от 1 до максимально доступной для винта запускаю тест:
#!/bin/bash FIO="/usr/bin/fio" config="read.ini" timeout=30 for device in sda do result="./fio_result.data."${device} max_depth=`cat /sys/block/${device}/device/queue_depth` for iodepth in `seq 1 ${max_depth}` do echo "[readtest]" > ${config} echo "blocksize=4k" >> ${config} echo "filename=/dev/"${device} >> ${config} echo "rw=randread" >> ${config} echo "direct=1" >> ${config} echo "buffered=0" >> ${config} echo "ioengine=libaio" >> ${config} echo "iodepth="${iodepth} >> ${config} echo "timeout="${timeout} >> ${config} A=`${FIO} ${config}` IOPS=`echo $A | awk -F"iops=" '{ print $2}' | awk '{print $1}'` CLAT=`echo $A | awk -F"clat" '{print $2}'| sed s/'('/''/g | awk -F"stdev" '{ print $1}' | sed s/','/''/g | awk '{print $1" "$4}' | sed s/'):'/''/g | sed s/'avg='/''/g` CLAT_AVG=`echo "$CLAT" | awk '{print $2 }'` CLAT_M=`echo "$CLAT" | awk '{print $1 }'` # if not msec if [ "$CLAT_M" = "usec" ] then CLAT_AVG=`echo "scale=2; $CLAT_AVG/1000" | bc` fi echo ${iodepth}" "$IOPS" "$CLAT_AVG >> ${result} echo ${iodepth}" "$IOPS" "$CLAT_AVG $CLAT_M done done
на выходе файл - что то вроде: глубина очереди, IOPS, Latency
1 54 18.21 2 61 32.05 3 66 44.69 4 71 55.39 5 78 62.83 6 75 78.87 7 83 82.54 8 84 93.89 9 86 102.97 10 89 110.95 11 87 124.08 12 92 128.32 13 93 136.95 14 93 148.65 15 91 161.93 16 96 164.10 17 98 170.55 18 97 183.16 19 96 195.36 20 95 207.68 21 97 213.97 22 97 223.03 23 98 231.33 24 100 237.42 25 99 249.03 26 101 254.15 27 103 259.39 28 101 272.94 29 101 283.66 30 98 302.42 31 103 295.61
Построение графиков
Строим график (с 2 осями )
#!/usr/bin/gnuplot -persist #set terminal png set terminal png size 1600,800 set output "FIO1_Speed_sda.png" set ylabel "IOPS" set xlabel "IODEPTH" #set grid #set y2tics 20 nomirror tc lt 2 set y2label 'ms' set ytics nomirror set y2tics set tics out set autoscale y set autoscale y2 #plot 2*x linetype 1, 4*x linetype 2 axes x1y2 plot \ "fio_result.data.sda" using 1:2 with linespoints lt rgb "red" lw 2 title "IOPS" axes x1y1, \ "fio_result.data.sda" using 1:3 with linespoints lt rgb "blue" lw 2 title "Latency, ms" axes x1y2
Как видно на графике, чем плотнее нагружен винт тем выше IOPS но тем больше фактическое ожидание у каждого запроса.
Сравнительные результаты тестирования
Выше результаты теста моего довольно старого ноутбучного винта (отсюда и такие невысокие результаты) Винт:
Model Family: Toshiba 2.5" HDD MK..52GSX Device Model: TOSHIBA MK1652GSX
INTEL SSDSA2CW080G3
Model Family: Intel 320 Series SSDs Device Model: INTEL SSDSA2CW080G3
OCZ-VERTEX2
Данные с сервера под нагрузкой!
Model Family: SandForce Driven SSDs Device Model: OCZ-VERTEX2
KINGSTON SVP200S390G
Device Model: KINGSTON SVP200S390G
Интерполяция
Когда точек много то удобнее использовать интерполяцию Для создания интерполированных графиков я использую следующий скрипт:
#!/usr/bin/gnuplot -persist #set terminal png set terminal png size 3600,800 set output "FIO1_Speed_sda.png" set ylabel "IOPS" set xlabel "IODEPTH" #set grid #set y2tics 20 nomirror tc lt 2 set y2label 'ms' set ytics nomirror set y2tics set tics out set autoscale y set autoscale y2 #plot 2*x linetype 1, 4*x linetype 2 axes x1y2 plot \ "fio_result.data.sda" using 1:2 with linespoints lt rgb "red" lw 1 title "IOPS" axes x1y1, \ "fio_result.data.sda" using 1:3 with linespoints lt rgb "blue" lw 1 title "Latency, ms" axes x1y2, \ "fio_result.data.sda" using 1:2 smooth bezier lt rgb "green" lw 3 title "IOPS" axes x1y1, \ "fio_result.data.sda" using 1:3 smooth bezier lt rgb "magenta" lw 3 title "Latency, ms" axes x1y2
Результат выглядит так:
HP LOGICAL VOLUME
Несколько дисков сразу
Тест реального сервера с кучей винтов (старых)
Есть старая железка, с кучей винтов (достаточно старых, от 80 гиг) Для наглядности - делаю их полный тест
Line Read
Размер дисков разный, потому длинна линий разная. Например 5000 блоков по 8к - 40гб. (да, у меня еще работает такой диск)
9 Power_On_Half_Minutes 0x0032 089 089 000 Old_age Always - 56077h+01m
#!/usr/bin/gnuplot -persist #set terminal png set terminal png size 1600,800 set output "Line_Read_Speed_sda.png" set ylabel "Speed, MB/s" set xlabel "Offset" set title "Line Read" set grid plot \ "line_step_by_step_test_sda_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sda, MB/s", \ "line_step_by_step_test_sdb_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sdb, MB/s", \ "line_step_by_step_test_sdc_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sdc, MB/s", \ "line_step_by_step_test_sdd_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sdd, MB/s", \ "line_step_by_step_test_sde_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sde, MB/s", \ "line_step_by_step_test_sdg_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sdg, MB/s", \ "line_step_by_step_test_sdh_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sdh, MB/s", \ "line_step_by_step_test_sdj_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sdj, MB/s", \ "line_step_by_step_test_sdk_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read sdk, MB/s", \ "line_step_by_step_test_md126_line_step_by_step_test" using 1:2 smooth bezier lw 3 title "Line Read md127 (sdd+sdc), MB/s"
IOPS
Видно что начиная примерно с 20 потоков диски выходят на максимум IOPS и растет только время отклика, привожу 2 графика - полный и подробный начала шкалы
На свякий случай - скрипт построения графика, отрезать лишнее можно используя set xrange [0:20]
#!/usr/bin/gnuplot -persist #set terminal png set terminal png size 1600,800 set output "IOPS_nnm_no_limit.png" set ylabel "IOPS" set xlabel "IODEPTH" #set xrange [0:20] set grid set y2label 'ms' set ytics nomirror set y2tics set tics out set autoscale y set autoscale y2 plot \ "fio_result.data.sda_step_by_step_test" using 1:2 smooth bezier lw 2 title "sda IOPS" axes x1y1, \ "fio_result.data.sda_step_by_step_test" using 1:3 smooth bezier lw 3 title "sda Latency, ms" axes x1y2, \ "fio_result.data.sdb_step_by_step_test" using 1:2 smooth bezier lw 2 title "sdb IOPS" axes x1y1, \ "fio_result.data.sdb_step_by_step_test" using 1:3 smooth bezier lw 3 title "sdb Latency, ms" axes x1y2, \ "fio_result.data.sdc_step_by_step_test" using 1:2 smooth bezier lw 2 title "sdc IOPS" axes x1y1, \ "fio_result.data.sdc_step_by_step_test" using 1:3 smooth bezier lw 3 title "sdc Latency, ms" axes x1y2, \ "fio_result.data.sdd_step_by_step_test" using 1:2 smooth bezier lw 2 title "sdd IOPS" axes x1y1, \ "fio_result.data.sdd_step_by_step_test" using 1:3 smooth bezier lw 3 title "sdd Latency, ms" axes x1y2, \ "fio_result.data.sde_step_by_step_test" using 1:2 smooth bezier lw 2 title "sde IOPS" axes x1y1, \ "fio_result.data.sde_step_by_step_test" using 1:3 smooth bezier lw 3 title "sde Latency, ms" axes x1y2, \ "fio_result.data.sdg_step_by_step_test" using 1:2 smooth bezier lw 2 title "sdg IOPS" axes x1y1, \ "fio_result.data.sdg_step_by_step_test" using 1:3 smooth bezier lw 3 title "sdg Latency, ms" axes x1y2, \ "fio_result.data.sdh_step_by_step_test" using 1:2 smooth bezier lw 2 title "sdh IOPS" axes x1y1, \ "fio_result.data.sdh_step_by_step_test" using 1:3 smooth bezier lw 3 title "sdh Latency, ms" axes x1y2, \ "fio_result.data.sdj_step_by_step_test" using 1:2 smooth bezier lw 2 title "sdj IOPS" axes x1y1, \ "fio_result.data.sdj_step_by_step_test" using 1:3 smooth bezier lw 3 title "sdj Latency, ms" axes x1y2, \ "fio_result.data.sdk_step_by_step_test" using 1:2 smooth bezier lw 2 title "sdk IOPS" axes x1y1, \ "fio_result.data.sdk_step_by_step_test" using 1:3 smooth bezier lw 3 title "sdk Latency, ms" axes x1y2, \ "fio_result.data.md126_step_by_step_test" using 1:2 smooth bezier lw 2 title "md126 (sdc+sdd) IOPS" axes x1y1, \ "fio_result.data.md126_step_by_step_test" using 1:3 smooth bezier lw 3 title "md126 (sdd+sdc)Latency, ms" axes x1y2
Одновременный тест нескольких винтов или насыщение шины
Проверим, а как насчет одновременной работы более чем 1 винта - не упираемся ли в шину.
Графиков довольно много, понять что то - сложно, но вцелом вывод такой - одиночный винт работает быстрее Чем если с ним параллельно нагружен второй. Куда происходит "упирание" сказать сложно.
один и то те винт при разной нагрузке на систему
sda
Видно, что при нагрузке на второй винт на этом же контроллере производительность падает. Дальше, нагрузка на другие винты практически не оказывает влияния.