Наблюдаемый эффект является по существу правильным, но метод имеет недостатки по крайней мере по двум причинам.
Тестируются буферы разных размеров, а не файлы разных размеров. Это связано с тем, что dd инструктируется для чтения и записи из одних и тех же двух файлов, в то время как изменяется только параметр bs=
(размер фрагментов чтения и записи).
На скорость вывода /dev /zero будет влиять размер (или буфер) запроса на чтение, поскольку он доставит запрошенное количество байтов. Об этом сообщают входящие-выездные записи.
Очевидное замедление на 1 байт вызвано тем фактом, что создание файла занимает относительно больше времени, чем чтение и запись содержимого, в то время как при увеличении скорости при 10 КБ создание файла перестает доминировать в общем времени для пробный. С этого момента снижение скорости определяется скоростью последовательной (последовательной) записи носителя, на котором находится тестовый файл.
Чтобы провести сравнительный анализ относительной скорости файлов разных размеров, вы должны разделить определенное количество данных между файлами, например:
100MB to 10 files
10MB to 100 files,
1MB to 100 files,
500KB to 204 files,
64K to 1600 files
1K to 102400 files.
В игру вступают и другие факторы, такие как размер блока / сектора носителя и файловая система (размер блока), минимальный размер выделения для одного файла.
Реакции на комментарий от опилок.
"Bs" в команде dd относится к размеру блока, и в сочетании с подсчетом для расчета скорости ввода-вывода указывается подходящий размер передачи
Подходящий и точный размер может быть выбран с этими двумя, но скорость ввода / вывода будет хуже для очень низкого bs=
. Из того, что я знаю (man dd, GNU Coreutils), параметр dd bs=BYTES
объясняется как "чтение и запись до байтов байтов за раз". Для меня это звучит так:
int bs // read upto bs bytes in each read operation.
byte[] buffer
while ( bs = file.readIntobufferAndReturnBytesRead(buffer) ) {
... use data in buffer
}
Другими словами, много маленьких операций чтения и записи займет больше времени, чем одно большое. Если вы считаете, что это фиктивное заявление, вы можете провести эксперимент, в котором вы сначала наполняете ведро объемом 5 л чайными ложками и сравниваете необходимое время для выполнения той же задачи с помощью чашек. Если вам больше знакомо внутреннее функционирование dd
, пожалуйста, представьте доказательства того, почему bs=
"размер блока" и что это означает в коде.
Вот почему мое второе утверждение имеет смысл:
исправлено trial.sh:
MB10="
10MB 1
1MB 10
512KB 20
256KB 40
128KB 80
64KB 160
32KB 320
16KB 640
4KB 2560
1KB 10240
512 20480
64 163840
1 10485760
"
BLOCKS100="
10MB 100
1MB 100
512KB 100
256KB 100
128KB 100
64KB 100
32KB 100
16KB 100
4KB 100
1KB 100
512 100
256 100
128 100
64 100
32 100
16 100
4 100
1 100
"
function trial {
BS=(`echo -e "$1" | awk '{print $1}'`)
CO=(`echo -e "$1" | awk '{print $2}'`)
printf "%-8s %-18s %7s %12s %8s\n" bs count data time speed
for ((i=0;i<${#BS[@]};i++ )); do
printf "%-8s %-18s" "bs=${BS[i]}" "count=${CO[i]}"
dd if=/dev/zero of=/dev/null bs=${BS[i]} count=${CO[i]} \
|& awk '/bytes/ { printf "%10s %-12s %8s\n", $3" "$4, $6, $8""$9 }'
done
echo
}
trial "$BLOCKS100"
trial "$MB10"
,
$ sh trial.sh
bs count data time speed
bs=10MB count=100 (1.0 GB) 0.781882 1.3GB/s
bs=1MB count=100 (100 MB) 0.0625649 1.6GB/s
bs=512KB count=100 (51 MB) 0.0193581 2.6GB/s
bs=256KB count=100 (26 MB) 0.00990991 2.6GB/s
bs=128KB count=100 (13 MB) 0.00517942 2.5GB/s
bs=64KB count=100 (6.4 MB) 0.00299067 2.1GB/s
bs=32KB count=100 (3.2 MB) 0.00166215 1.9GB/s
bs=16KB count=100 (1.6 MB) 0.00111013 1.4GB/s
bs=4KB count=100 (400 kB) 0.000552862 724MB/s
bs=1KB count=100 (100 kB) 0.000385104 260MB/s
bs=512 count=100 (51 kB) 0.000357936 143MB/s
bs=256 count=100 (26 kB) 0.000509282 50.3MB/s
bs=128 count=100 (13 kB) 0.000419117 30.5MB/s
bs=64 count=100 (6.4 kB) 0.00035179 18.2MB/s
bs=32 count=100 (3.2 kB) 0.000352209 9.1MB/s
bs=16 count=100 (1.6 kB) 0.000341594 4.7MB/s
bs=4 count=100 (400 B) 0.000336425 1.2MB/s
bs=1 count=100 (100 B) 0.000345085 290kB/s
bs count data time speed
bs=10MB count=1 (10 MB) 0.0177581 563MB/s 566MB/s 567MB/s
bs=1MB count=10 (10 MB) 0.00759677 1.3GB/s 1.3GB/s 1.2GB/s
bs=512KB count=20 (10 MB) 0.00545376 1.9GB/s 1.9GB/s 1.8GB/s
bs=256KB count=40 (10 MB) 0.00416945 2.5GB/s 2.4GB/s 2.4GB/s
bs=128KB count=80 (10 MB) 0.00396747 2.6GB/s 2.5GB/s 2.6GB/s
bs=64KB count=160 (10 MB) 0.00446215 2.3GB/s 2.5GB/s 2.5GB/s
bs=32KB count=320 (10 MB) 0.00451118 2.3GB/s 2.4GB/s 2.4GB/s
bs=16KB count=640 (10 MB) 0.003922 2.6GB/s 2.5GB/s 2.5GB/s
bs=4KB count=2560 (10 MB) 0.00613164 1.7GB/s 1.6GB/s 1.7GB/s
bs=1KB count=10240 (10 MB) 0.0154327 664MB/s 655MB/s 626MB/s
bs=512 count=20480 (10 MB) 0.0279125 376MB/s 348MB/s 314MB/s
bs=64 count=163840 (10 MB) 0.212944 49.2MB/s 50.5MB/s 52.5MB/s
bs=1 count=10485760 (10 MB) 16.0154 655kB/s 652kB/s 640kB/s
Соответствующая часть для второго недостатка - это когда размер данных постоянен (10 МБ).
Скорости, очевидно, медленнее для очень маленьких кусков. Я не уверен, как объяснить "падение" при bs = 10 МБ, но я могу предположить, что это связано с тем, как dd обрабатывает буферизацию для больших кусков.
Я должен был докопаться до этого (спасибо опилкам за то, что оспорил мое предположение) ...
Похоже, мое предположение о размере буфера == bs неверно, но не полностью ложно, потому что параметр bs влияет на размер, как продемонстрировано для dd, который печатает размер буфера. Это означает, что мой второй недостаток не относится к файлам <8K в системах, где размер страницы составляет 4K:
$ ./dd if=/dev/zero of=/dev/null bs=1 count=1
OUTPUT_BLOCK_SLOP: 4095
MALLOC INPUT_BLOCK_SLOP: 8195, ibuf: 8196
1+0 records in
1+0 records out
1 byte (1 B) copied, 0.000572 s, 1.7 kB/s
$ ./dd if=/dev/zero of=/dev/null bs=1805 count=1
OUTPUT_BLOCK_SLOP: 4095
MALLOC INPUT_BLOCK_SLOP: 8195, ibuf: 10000
1+0 records in
1+0 records out
1805 bytes (1.8 kB) copied, 0.000450266 s, 4.0 MB/s
(dd.c из coreutils 8.20)
line:text
21: #define SWAB_ALIGN_OFFSET 2
97: #define INPUT_BLOCK_SLOP (2 * SWAB_ALIGN_OFFSET + 2 * page_size - 1)
98: #define OUTPUT_BLOCK_SLOP (page_size - 1)
1872: real_buf = malloc (input_blocksize + INPUT_BLOCK_SLOP); // ibuf
1889: real_obuf = malloc (output_blocksize + OUTPUT_BLOCK_SLOP); // obuf
// if conversion is on, othervise obuf=ibuf
2187: page_size = getpagesize ();
человек 3 memcpy
void *memcpy(void *dest, const void *src, size_t n);
The memcpy() function copies n bytes from memory area src to memory area
dest. The memory areas must not overlap. Use memmove(3) if the memory
areas do overlap.