Вот некоторые результаты команды dd :

$ dd if=/dev/zero of=test.file bs=10M count=1
1+0 records in
1+0 records out
10485760 bytes (10 MB) copied, 0.130214 s, 80.5 MB/s
$ dd if=/dev/zero of=test.file bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.00683995 s, 153 MB/s
$ dd if=/dev/zero of=test.file bs=512k count=1
1+0 records in
1+0 records out
524288 bytes (524 kB) copied, 0.0029348 s, 179 MB/s
$ dd if=/dev/zero of=test.file bs=10k count=1
1+0 records in
1+0 records out
10240 bytes (10 kB) copied, 0.000199126 s, 51.4 MB/s
$ dd if=/dev/zero of=test.file bs=1k count=1
1+0 records in
1+0 records out
1024 bytes (1.0 kB) copied, 0.000133526 s, 7.7 MB/s
$ dd if=/dev/zero of=test.file bs=1 count=1
1+0 records in
1+0 records out
1 byte (1 B) copied, 0.000149828 s, 6.7 kB/s

Почему скорость "горб" на 10k?
Почему кажется, что скорость НАМНОГО медленнее при очень маленьких размерах файлов?

2 ответа2

3

Наблюдаемый эффект является по существу правильным, но метод имеет недостатки по крайней мере по двум причинам.

  • Тестируются буферы разных размеров, а не файлы разных размеров. Это связано с тем, что 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.
0

Небольшие файлы требуют остановки ОС и создания записей каталога для каждого файла. Таким образом, 100 МБ имеет 1 запись каталога, а затем данные. У 100 файлов размером 1 Мб есть 100 записей каталога, каждая из которых требует времени для создания. Также требуется время, чтобы найти следующий свободный сектор и немного больше времени, чтобы перейти к этому сектору и начать писать. Действительно небольшие файлы будут иметь неточные тайминги. Операция выполняется в памяти и записи на диск всякий раз, когда ОС чувствует себя так, как она. Тогда время представляет собой время, которое потребовалось, чтобы сделать это в памяти, а не на диске. Если у вас нет RAID, SSD или другого суперскоростного хранилища, скорость памяти> 100 Мбит / с.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .