Buone dimensioni del blocco per la clonazione del disco con diskdump (dd)


47

Uso dd nella sua forma più semplice per clonare un disco rigido:

dd if=INPUT of=OUTPUT

Tuttavia, ho letto nella manpage che dd conosce un parametro di dimensione blocchi. Esiste un valore ottimale per il parametro blockize che accelera la procedura di clonazione?


Risposte:


32

64k sembra essere una buona scelta:

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

(preso da qui ).

questo corrisponde alle mie scoperte relative al buffering di lettura / scrittura per accelerare un programma di conversione io-pesante che una volta stavo sfruttando @work.


Si noti che questo benchmark potrebbe apparire diverso per unità rotanti e SSD.
Jiri,

3
-1 Dipende quasi completamente dal disco rigido. Descrivere piuttosto la procedura utilizzata per ottenere questi valori in modo che l'OP possa ripetere i passaggi per ottenere la dimensione di blocco ottimale per il proprio disco rigido. Inoltre, non hai elencato 64k nel tuo elenco di risultati e tutti i risultati oltre 1k sono più o meno gli stessi.
Micheal Johnson,

@MichealJohnson sentiti libero di modificare questo post e prendere la descrizione di come quella tabella è stata generata dal link fornito e incollarlo qui. 64k è il primo valore che sembra non produrre ulteriori miglioramenti in termini di velocità E è un allineamento naturale. e sì, è ovvio che la velocità misurata dipende completamente dall'hardware utilizzato. questo era vero 5 anni fa ed è vero ora.
Akira,

1
Perché 64k? Per me 2k non produce alcun ulteriore miglioramento e quindi 1k è il valore migliore ed è anche un allineamento naturale come 64k.
Micheal Johnson,

La dimensione del blocco modifica le prestazioni della scheda SD o taglia solo le dimensioni del file in movimento utilizzando da dd a sdcard?
Trismegisto,

23

dd copierà felicemente usando la BS di qualunque cosa tu voglia e copierà un blocco parziale (alla fine).

Fondamentalmente, il parametro size block (bs) sembra impostare la quantità di memoria utilizzata per leggere un grumo da un disco prima di provare a scrivere quel grumo nell'altro.

Se disponi di molta RAM, aumentare le dimensioni del BS (ma interamente contenuto nella RAM) significa che il sottosistema I / O viene utilizzato il più possibile eseguendo letture e scritture di grandi dimensioni, sfruttando la RAM. Ridurre la BS significa che il sovraccarico I / O in proporzione all'attività totale aumenta.

Naturalmente in questo c'è una legge di rendimenti decrescenti. La mia approssimazione approssimativa è che una dimensione del blocco nell'intervallo tra 128 K e 32 M probabilmente fornirà prestazioni tali che le spese generali sono piccole rispetto al semplice I / O e che aumentando non farà molta differenza. Il motivo per cui il limite inferiore è compreso tra 128 K e 32 M è: dipende dal sistema operativo, dall'hardware e così via.

Se fossi in me, farei alcuni esperimenti per cronometrare una copia / clone usando un BS di 128K e di nuovo usando (diciamo) 16M. Se uno è notevolmente più veloce, usalo. In caso contrario, utilizzare la BS più piccola delle due.


10

Per quelli che finiscono qui tramite Google, anche se questa discussione è un po 'vecchia ...

Tieni presente che dd è stupido per un motivo: più è semplice, meno modi può rovinare.

Schemi di partizionamento complessi (considera un disco rigido a doppio avvio che utilizza inoltre LVM per il suo sistema Linux) inizieranno a rimuovere i bug dalla falegnameria in programmi come Clonezilla. I filesystem mal montati male possono far saltare ntfsclone alle stelle.

Un filesystem corrotto clonato settore per settore non è peggio dell'originale. Un filesystem corrotto dopo una "copia intelligente" non riuscita potrebbe essere VERAMENTE dispiaciuto.

In caso di dubbio, usa dd e diventa forense. L'imaging forense richiede copie settore per settore (in effetti, può richiedere più settori di quelli che riuscirai a realizzare con dd, ma questa è una lunga storia). È lento e noioso, ma farà il lavoro correttamente.

Inoltre, impara a conoscere le opzioni "conv = noerror, sync", in modo da poter clonare unità che stanno iniziando a guastarsi o creare ISO da CD graffiati ( tosse ) senza che siano necessari mesi.


Cosa fa l' syncopzione? La pagina man dice semplicemente: "use synchronized I/O for data and metadata". Con cosa ci stiamo sincronizzando? Possono essere molte cose diverse.
Sherrellbc,

1
La sincronizzazione @sherrellbc riempie i blocchi di input di zero in caso di errori di lettura, quindi gli offset dei dati rimangono sincronizzati.
goetzc,

9

Come altri hanno già detto, non esiste una dimensione di blocco universalmente corretta; ciò che è ottimale per una situazione o un componente hardware può essere terribilmente inefficiente per un altro. Inoltre, a seconda dell'integrità dei dischi, può essere preferibile utilizzare una dimensione di blocco diversa da quella "ottimale".

Una cosa abbastanza affidabile sull'hardware moderno è che la dimensione del blocco predefinita di 512 byte tende a essere quasi un ordine di grandezza più lento di un'alternativa più ottimale. In caso di dubbio, ho scoperto che 64 KB è un default moderno piuttosto solido. Sebbene 64K di solito non siano le dimensioni ottimali del blocco, nella mia esperienza tende ad essere molto più efficiente di quello predefinito. 64K ha anche una storia piuttosto solida di essere affidabile: puoi trovare un messaggio dalla mailing list di Eug-Lug, circa 2002, raccomandando qui una dimensione del blocco di 64K: http://www.mail-archive.com/eug- lug@efn.org/msg12073.html

Per determinare la dimensione ottimale del blocco di output, ho scritto il seguente script che verifica la scrittura di un file di test da 128 M con dd in un intervallo di diverse dimensioni di blocco, da un valore predefinito di 512 byte a un massimo di 64 MB. Attenzione, questo script usa dd internamente, quindi usa con cautela.

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

Visualizza su GitHub

Ho testato questo script solo su un sistema Debian (Ubuntu) e su OSX Yosemite, quindi probabilmente ci vorranno alcune modifiche per far funzionare altri sapori Unix.

Per impostazione predefinita, il comando creerà un file di test denominato dd_obs_testfile nella directory corrente. In alternativa, è possibile fornire un percorso a un file di test personalizzato fornendo un percorso dopo il nome dello script:

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

L'output dello script è un elenco delle dimensioni dei blocchi testati e delle rispettive velocità di trasferimento in questo modo:

$ ./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

(Nota: l'unità delle velocità di trasferimento varia in base al sistema operativo)

Per testare le dimensioni ottimali del blocco di lettura, puoi usare più o meno lo stesso processo, ma invece di leggere da / dev / zero e scrivere sul disco, dovresti leggere dal disco e scrivere su / dev / null. Una sceneggiatura per farlo potrebbe apparire così:

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

Visualizza su GitHub

Una differenza importante in questo caso è che il file di test è un file scritto dallo script. Non puntare questo comando su un file esistente o il file esistente verrà sovrascritto con dati casuali!

Per il mio hardware particolare ho scoperto che 128K era la dimensione del blocco di input più ottimale su un HDD e 32K era il più ottimale su un SSD.

Sebbene questa risposta copra la maggior parte delle mie scoperte, mi sono imbattuto in questa situazione abbastanza volte da aver scritto un post sul blog al riguardo: http://blog.tdg5.com/tuning-dd-block-size/ Puoi trovare ulteriori dettagli sui test che ho eseguito lì.

Questo post StackOverflow può anche essere utile: dd: come calcolare la dimensione di blocco ottimale?



1

clonazione della vecchia unità di avvio su new ssd su sata esterno (da ssd a ssd)

  • usando Linux Ubuntu 18.04.2 LTS 64 bit
  • hp xw4600 (8 GB di RAM, Intel Core 2 Quad Q6700 a 2,66 GHz 4c / 4t no-HT)

utilizzando Disks (strumento)> formato> 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 (vecchio; i dischi riportano una velocità media di 263 MB / s con picchi vicini a 270 MB / s - nessun test di scrittura a causa del disco di sistema)
  • sdf: Crucial MX500, 500GB, CT500MX500SSD1 (Rapporti dischi: velocità media r / wr 284/262 MB / se tempo di accesso 0,05 ms, con picchi a circa 290/270 MB / s)

Esecuzioni di test:

$ 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
#                                            *********  ********

secondo tentativo dopo la cancellazione sicura con lo stesso risultato:

128035676160 bytes (128 GB, 119 GiB) copied, 472,797 s, 271 MB/s

Benvenuto in Super User! Grazie per la tua risposta, ma ti suggerirei di modificarlo per includere il riepilogo; tra tutti i risultati citati, ho trovato difficile trovare qual è la tua vera risposta! Saluti
bertieb
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.