Dobry rozmiar bloku do klonowania dysku za pomocą zrzutu dysku (dd)

46

Używam dd w najprostszej formie do klonowania dysku twardego:

dd if=INPUT of=OUTPUT

Jednak przeczytałem na stronie podręcznika, że ​​dd zna parametr wielkości bloku. Czy istnieje optymalna wartość parametru wielkości bloku, który przyspieszy procedurę klonowania?

Phi
źródło

Odpowiedzi:

32

64k wydaje się być dobrym wyborem:

Results:

  no bs=        78s     144584+0 records
  bs=512        78s     144584+0 records
  bs=1k         38s     72292+0 records
  bs=2k         38s     36146+0 records
  bs=4k         38s     18073+0 records
  bs=5k         39s     14458+1 records
  bs=50k        38s     1445+1 records
  bs=500k       39s     144+1 records
  bs=512k       39s     144+1 records
  bs=1M         39s     72+1 records
  bs=5M         39s     14+1 records
  bs=10M        39s     7+1 records

(wzięte stąd ).

zgadza się to z moimi własnymi ustaleniami dotyczącymi buforowania odczytu / zapisu w celu przyspieszenia ciężkiego programu konwertującego io, który kiedyś pimping @work.

akira
źródło
Pamiętaj, że ten test porównawczy może wyglądać inaczej w przypadku obracających się dysków i dysków SSD.
Jiri,
3
-1 Jest to prawie całkowicie zależne od twojego dysku twardego. Raczej opisz procedurę zastosowaną do uzyskania tych wartości, aby OP mógł powtórzyć kroki, aby uzyskać optymalny rozmiar bloku dla własnego dysku twardego. Ponadto nie ma na liście 64k wyników i wszystkie wyniki po 1k są mniej więcej takie same.
Micheal Johnson,
@MichealJohnson możesz edytować ten post i wziąć opis, jak ta tabela została wygenerowana z podanego linku, i wklej go tutaj. 64k to pierwsza wartość, która wydaje się nie przynosić dalszej poprawy pod względem prędkości ORAZ jest naturalnym wyrównaniem. i tak, oczywiste jest, że zmierzona prędkość zależy całkowicie od używanego sprzętu. było to prawdą 5 lat temu i jest teraz prawdą.
akira,
1
Dlaczego 64k? Dla mnie 2k nie daje żadnej dalszej poprawy, więc 1k jest najlepszą wartością, a także jest tak naturalnym wyrównaniem jak 64k.
Micheal Johnson
Czy rozmiar bloku zmienia wydajność karty SD, czy tylko zmniejsza rozmiar przenoszonego pliku przy użyciu dd na sdcard?
Trismegistos
22

dd z przyjemnością skopiuje używając BS tego, co chcesz i skopiuje częściowy blok (na końcu).

Zasadniczo parametr rozmiar bloku (bs) wydaje się ustawiać ilość pamięci, która była używana do odczytania bryły z jednego dysku przed próbą zapisania tej bryły na drugim.

Jeśli masz dużo pamięci RAM, to powiększenie stacji bazowej BS (ale całkowicie zawartej w pamięci RAM) oznacza, że ​​podsystem I / O jest wykorzystywany w jak największym stopniu przez wykonywanie ogromnie dużych odczytów i zapisów - z wykorzystaniem pamięci RAM. Niewielkie BS oznacza, że ​​zwiększa się narzut I / O jako odsetek całkowitej aktywności.

Oczywiście w tym jest prawo malejących zysków. Moje przybliżone przybliżenie jest takie, że rozmiar bloku w zakresie około 128K do 32M prawdopodobnie da wydajność tak, że koszty ogólne są małe w porównaniu do zwykłego wejścia / wyjścia, a powiększenie nie zrobi dużej różnicy. Przyczyną dolnej granicy jest 128K do 32M jest - zależy to od twojego systemu operacyjnego, sprzętu i tak dalej.

Gdybym to był ja, zrobiłbym kilka eksperymentów mierzących czas kopiowania / klonowania przy użyciu BS 128K i ponownie przy użyciu (powiedzmy) 16M. Jeśli ktoś jest znacznie szybszy, użyj go. Jeśli nie, użyj mniejszej BS z dwóch.

szybko
źródło
10

Dla tych, którzy kończą tutaj przez Google, nawet jeśli ta dyskusja jest trochę stara ...

Pamiętaj, że dd jest głupi z jakiegoś powodu: im prościej, tym mniej sposobów może to popsuć.

Skomplikowane schematy partycjonowania (rozważ dysk twardy z podwójnym uruchomieniem, który dodatkowo wykorzystuje LVM w systemie Linux), zaczną wyciągać błędy z stolarki w programach takich jak Clonezilla. Źle odmontowane systemy plików mogą zdmuchnąć ntfsclone w górę.

Uszkodzony system plików sklonowany sektor po sektorze nie jest gorszy niż oryginał. Uszkodzony system plików po nieudanej „inteligentnej kopii” może mieć NAPRAWDĘ przykro.

W razie wątpliwości użyj dd i przejdź do analizy sądowej. Obrazowanie kryminalistyczne wymaga kopii sektor po sektorze (w rzeczywistości może wymagać więcej sektorów niż będziesz w stanie uzyskać dzięki dd, ale to długa historia). Jest powolny i żmudny, ale wykona zadanie poprawnie.

Również poznać opcje „conv = noerror, Sync”, dzięki czemu można klonować dyski, które zaczynają fail-- lub dokonać obrazy ISO z porysowanych ( kaszel ) CDs-- bez niego biorąc miesięcy.

Matt Heck
źródło
Co robi syncopcja? Strona człowiek po prostu mówi: "use synchronized I/O for data and metadata". Z czym się synchronizujemy? To może być wiele różnych rzeczy.
sherrellbc
1
Synchronizacja @sherrellbc wypełnia bloki wejściowe zerami, jeśli wystąpiły jakiekolwiek błędy odczytu, więc przesunięcia danych pozostają zsynchronizowane.
goetzc
9

Jak powiedzieli inni, nie ma uniwersalnie poprawnego rozmiaru bloku; to, co jest optymalne dla jednej sytuacji lub jednego elementu sprzętu, może być strasznie nieefektywne w innym. Ponadto, w zależności od kondycji dysków, może być zalecane użycie innego rozmiaru bloku niż ten, który jest „optymalny”.

Jedną z rzeczy, która jest dość niezawodna na współczesnym sprzęcie, jest to, że domyślny rozmiar 512 bajtów jest prawie o rząd wielkości wolniejszy niż bardziej optymalna alternatywa. W razie wątpliwości stwierdziłem, że 64K to dość solidne, nowoczesne ustawienie domyślne. Chociaż 64K zwykle nie jest optymalnym rozmiarem bloku, z mojego doświadczenia wynika, że ​​jest o wiele bardziej wydajny niż domyślny. 64K ma również dość solidną historię niezawodności: możesz znaleźć wiadomość z listy mailingowej Eug-Lug, około 2002, zalecając rozmiar bloku 64K tutaj: http://www.mail-archive.com/eug- [email protected]/msg12073.html

Aby określić optymalny rozmiar bloku wyjściowego, napisałem następujący skrypt, który testuje zapisanie pliku testowego 128M z dd w zakresie różnych rozmiarów bloku, od domyślnej 512 bajtów do maksymalnie 64M. Ostrzegam, ten skrypt używa dd wewnętrznie, więc używaj go ostrożnie.

dd_obs_test.sh:

#!/bin/bash

# Since we're dealing with dd, abort if any errors occur
set -e

TEST_FILE=${1:-dd_obs_testfile}
TEST_FILE_EXISTS=0
if [ -e "$TEST_FILE" ]; then TEST_FILE_EXISTS=1; fi
TEST_FILE_SIZE=134217728

if [ $EUID -ne 0 ]; then
  echo "NOTE: Kernel cache will not be cleared between tests without sudo. This will likely cause inaccurate results." 1>&2
fi

# Header
PRINTF_FORMAT="%8s : %s\n"
printf "$PRINTF_FORMAT" 'block size' 'transfer rate'

# Block sizes of 512b 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M
for BLOCK_SIZE in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864
do
  # Calculate number of segments required to copy
  COUNT=$(($TEST_FILE_SIZE / $BLOCK_SIZE))

  if [ $COUNT -le 0 ]; then
    echo "Block size of $BLOCK_SIZE estimated to require $COUNT blocks, aborting further tests."
    break
  fi

  # Clear kernel cache to ensure more accurate test
  [ $EUID -eq 0 ] && [ -e /proc/sys/vm/drop_caches ] && echo 3 > /proc/sys/vm/drop_caches

  # Create a test file with the specified block size
  DD_RESULT=$(dd if=/dev/zero of=$TEST_FILE bs=$BLOCK_SIZE count=$COUNT conv=fsync 2>&1 1>/dev/null)

  # Extract the transfer rate from dd's STDERR output
  TRANSFER_RATE=$(echo $DD_RESULT | \grep --only-matching -E '[0-9.]+ ([MGk]?B|bytes)/s(ec)?')

  # Clean up the test file if we created one
  if [ $TEST_FILE_EXISTS -ne 0 ]; then rm $TEST_FILE; fi

  # Output the result
  printf "$PRINTF_FORMAT" "$BLOCK_SIZE" "$TRANSFER_RATE"
done

Zobacz na GitHub

Testowałem ten skrypt tylko w systemie Debian (Ubuntu) i OSX Yosemite, więc prawdopodobnie zajmie trochę ulepszeń, aby działać na innych smakach Uniksa.

Domyślnie polecenie utworzy plik testowy o nazwie dd_obs_testfile w bieżącym katalogu. Alternatywnie możesz podać ścieżkę do niestandardowego pliku testowego, podając ścieżkę po nazwie skryptu:

$ ./dd_obs_test.sh /path/to/disk/test_file

Dane wyjściowe skryptu to lista testowanych rozmiarów bloków i odpowiadających im szybkości przesyłania, takich jak:

$ ./dd_obs_test.sh
block size : transfer rate
       512 : 11.3 MB/s
      1024 : 22.1 MB/s
      2048 : 42.3 MB/s
      4096 : 75.2 MB/s
      8192 : 90.7 MB/s
     16384 : 101 MB/s
     32768 : 104 MB/s
     65536 : 108 MB/s
    131072 : 113 MB/s
    262144 : 112 MB/s
    524288 : 133 MB/s
   1048576 : 125 MB/s
   2097152 : 113 MB/s
   4194304 : 106 MB/s
   8388608 : 107 MB/s
  16777216 : 110 MB/s
  33554432 : 119 MB/s
  67108864 : 134 MB/s

(Uwaga: Jednostka szybkości przesyłania różni się w zależności od systemu operacyjnego)

Aby przetestować optymalny rozmiar bloku odczytu, możesz użyć mniej więcej tego samego procesu, ale zamiast czytać z / dev / zero i zapisywać na dysku, możesz czytać z dysku i zapisywać na / dev / null. Skrypt do wykonania tego może wyglądać tak:

dd_ibs_test.sh:

#!/bin/bash

# Since we're dealing with dd, abort if any errors occur
set -e

TEST_FILE=${1:-dd_ibs_testfile}
if [ -e "$TEST_FILE" ]; then TEST_FILE_EXISTS=$?; fi
TEST_FILE_SIZE=134217728

# Exit if file exists
if [ -e $TEST_FILE ]; then
  echo "Test file $TEST_FILE exists, aborting."
  exit 1
fi
TEST_FILE_EXISTS=1

if [ $EUID -ne 0 ]; then
  echo "NOTE: Kernel cache will not be cleared between tests without sudo. This will likely cause inaccurate results." 1>&2
fi

# Create test file
echo 'Generating test file...'
BLOCK_SIZE=65536
COUNT=$(($TEST_FILE_SIZE / $BLOCK_SIZE))
dd if=/dev/urandom of=$TEST_FILE bs=$BLOCK_SIZE count=$COUNT conv=fsync > /dev/null 2>&1

# Header
PRINTF_FORMAT="%8s : %s\n"
printf "$PRINTF_FORMAT" 'block size' 'transfer rate'

# Block sizes of 512b 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M
for BLOCK_SIZE in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864
do
  # Clear kernel cache to ensure more accurate test
  [ $EUID -eq 0 ] && [ -e /proc/sys/vm/drop_caches ] && echo 3 > /proc/sys/vm/drop_caches

  # Read test file out to /dev/null with specified block size
  DD_RESULT=$(dd if=$TEST_FILE of=/dev/null bs=$BLOCK_SIZE 2>&1 1>/dev/null)

  # Extract transfer rate
  TRANSFER_RATE=$(echo $DD_RESULT | \grep --only-matching -E '[0-9.]+ ([MGk]?B|bytes)/s(ec)?')

  printf "$PRINTF_FORMAT" "$BLOCK_SIZE" "$TRANSFER_RATE"
done

# Clean up the test file if we created one
if [ $TEST_FILE_EXISTS -ne 0 ]; then rm $TEST_FILE; fi

Zobacz na GitHub

Ważną różnicą w tym przypadku jest to, że plik testowy jest plikiem zapisanym przez skrypt. Nie kieruj tego polecenia na istniejący plik, ponieważ istniejący plik zostanie zastąpiony losowymi danymi!

W przypadku mojego konkretnego sprzętu stwierdziłem, że 128K jest najbardziej optymalnym rozmiarem bloku wejściowego na HDD, a 32K jest najbardziej optymalnym na SSD.

Chociaż ta odpowiedź obejmuje większość moich ustaleń, wystarczająco często napotykałem tę sytuację, że napisałem o niej post na blogu: http://blog.tdg5.com/tuning-dd-block-size/ Możesz znaleźć więcej szczegółów na testach, które tam przeprowadziłem.

Ten post StackOverflow może być również pomocny: dd: Jak obliczyć optymalny rozmiar bloku?

tdg5
źródło
3

Tak, ale nie znajdziesz go bez wielu testów. Przekonałem się, że 32M to dobra wartość do użycia.

Ignacio Vazquez-Abrams
źródło
1

klonowanie starego dysku rozruchowego na nowy dysk SSD na zewnętrznym dysku SATA (SSD na SSD)

  • używając Linuksa Ubuntu 18.04.2 LTS 64bit
  • hp xw4600 (8 GB pamięci RAM, Intel Core 2 Quad Q6700 @ 2,66 GHz 4c / 4t bez HT)

using Disks (tool)> format> ATA Secure Erase (2min)

$ lsblk -l /dev/sd?
NAME MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda    8:0    0 119,2G  0 disk 
sda1   8:1    0 119,2G  0 part /
sdb    8:16   0   2,7T  0 disk 
sdc    8:32   0   2,7T  0 disk 
sdd    8:48   0  12,8T  0 disk 
sde    8:64   0   2,7T  0 disk
sdf    8:80   1 465,8G  0 disk 

$ sudo fdisk -l /dev/sda
Disk /dev/sda: 119,2 GiB, 128035676160 bytes, 250069680 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

$ sudo fdisk -l /dev/sdf
Disk /dev/sdf: 465,8 GiB, 500107862016 bytes, 976773168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
  • sda: Kingston SSD (stary; dyski zgłaszają średnią prędkość rd 263 MB / s przy szczytach zbliżonych do 270 MB / s - brak testu zapisu z powodu dysku systemowego)
  • sdf: Crucial MX500, 500 GB, CT500MX500SSD1 (raporty dysków: średnia szybkość rd / wr 284/262 MB / s, a czas dostępu 0,05 ms, z pikami około 290/270 MB / s)

Przebiegi testowe:

$ sudo dd if=/dev/sda of=/dev/sdf
250069680+0 records in
250069680+0 records out
128035676160 bytes (128 GB, 119 GiB) copied, 3391,72 s, 37,7 MB/s
#       --vvvvv--                            *********
$ sudo dd bs=1M if=/dev/sda of=/dev/sdf
122104+1 records in
122104+1 records out
128035676160 bytes (128 GB, 119 GiB) copied, 473,186 s, 271 MB/s
#                                            *********  ********

druga próba po bezpiecznym skasowaniu z tym samym rezultatem:

128035676160 bytes (128 GB, 119 GiB) copied, 472,797 s, 271 MB/s
kgSW.de
źródło
Witamy w Super User! Dziękuję za odpowiedź, ale proponuję ją edytować , aby zawierała podsumowanie; spośród wszystkich cytowanych wyników stwierdziłem, że trudno jest znaleźć rzeczywistą odpowiedź! Pozdrawiam
bertieb