GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Gute Blockgröße zum Klonen von Festplatten mit diskdump (dd)

64k scheint eine gute Wahl zu sein:

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

(entnommen von hier).

dies stimmt mit meinen eigenen Erkenntnissen über das Puffern von Lese-/Schreibvorgängen überein, um ein io-lastiges Konverterprogramm zu beschleunigen, das ich einmal an @work gepimpt habe.


dd kopiert gerne mit dem BS alles, was Sie wollen, und kopiert einen Teilblock (am Ende).

Grundsätzlich scheint der Blockgrößenparameter (bs) die Menge an Speicher festzulegen, die verwendet wird, um einen Klumpen von einer Festplatte einzulesen, bevor versucht wird, diesen Klumpen auf die andere zu schreiben.

Wenn Sie über viel RAM verfügen, bedeutet das Vergrößern des BS (aber vollständig im RAM enthalten), dass das E / A-Subsystem so weit wie möglich ausgelastet wird, indem massiv große Lese- und Schreibvorgänge durchgeführt werden - unter Ausnutzung des RAM. Wenn Sie den BS klein machen, bedeutet dies, dass der I/O-Overhead im Verhältnis zur Gesamtaktivität steigt.

Natürlich gibt es dabei ein Gesetz des abnehmenden Ertrags. Meine grobe Annäherung ist, dass eine Blockgröße im Bereich von etwa 128 KB bis 32 MB wahrscheinlich eine solche Leistung erbringen wird, dass der Overhead im Vergleich zur einfachen E / A gering ist und eine Vergrößerung keinen großen Unterschied macht. Der Grund dafür, dass die Untergrenze 128 KB bis 32 MB beträgt, ist, dass dies von Ihrem Betriebssystem, Ihrer Hardware usw. abhängt.

Wenn ich es wäre, würde ich ein paar Experimente durchführen, um eine Kopie/einen Klon mit einem BS von 128K und erneut mit (sagen wir) 16M zu timen. Wenn man merklich schneller ist, benutze es. Wenn nicht, dann verwenden Sie den kleineren BS der beiden.


Wie andere gesagt haben, gibt es keine allgemein korrekte Blockgröße; Was für eine Situation optimal ist, oder ein Hardwareteil kann für eine andere schrecklich ineffizient sein. Abhängig vom Zustand der Festplatten kann es auch vorzuziehen sein, eine andere Blockgröße als die "optimale" zu verwenden.

Eine Sache, die auf moderner Hardware ziemlich zuverlässig ist, ist, dass die Standard-Blockgröße von 512 Bytes dazu neigt, fast eine Größenordnung langsamer zu sein als eine optimalere Alternative. Im Zweifelsfall habe ich festgestellt, dass 64K ein ziemlich solider moderner Standard ist. Obwohl 64K normalerweise nicht DIE optimale Blockgröße ist, ist sie meiner Erfahrung nach viel effizienter als der Standardwert. 64K hat auch eine ziemlich solide Geschichte der zuverlässigen Leistung:Sie finden hier eine Nachricht von der Eug-Lug-Mailingliste, circa 2002, die eine Blockgröße von 64K empfiehlt:http://www.mail-archive.com/example@ unixlinux.online/msg12073.html

Um DIE optimale Ausgabeblockgröße zu bestimmen, habe ich das folgende Skript geschrieben, das das Schreiben einer 128 MB großen Testdatei mit dd bei einer Reihe unterschiedlicher Blockgrößen testet, von der Standardeinstellung von 512 Byte bis zu einem Maximum von 64 MB. Seien Sie gewarnt, dieses Skript verwendet intern dd, verwenden Sie es also mit Vorsicht.

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

Auf GitHub ansehen

Ich habe dieses Skript nur auf einem Debian (Ubuntu)-System und auf OSX Yosemite getestet, daher wird es wahrscheinlich einige Anpassungen erfordern, damit es auf anderen Unix-Varianten funktioniert.

Standardmäßig erstellt der Befehl eine Testdatei namens dd_obs_testfile im aktuellen Verzeichnis. Alternativ können Sie einen Pfad zu einer benutzerdefinierten Testdatei angeben, indem Sie nach dem Skriptnamen einen Pfad angeben:

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

Die Ausgabe des Skripts ist eine Liste der getesteten Blockgrößen und ihrer jeweiligen Übertragungsraten wie folgt:

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

(Hinweis:Die Einheit der Übertragungsraten variiert je nach Betriebssystem)

Um die optimale Leseblockgröße zu testen, könnten Sie mehr oder weniger denselben Prozess verwenden, aber anstatt von /dev/zero zu lesen und auf die Festplatte zu schreiben, würden Sie von der Festplatte lesen und nach /dev/null schreiben. Ein Skript dafür könnte so aussehen:

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

Auf GitHub ansehen

Ein wichtiger Unterschied besteht in diesem Fall darin, dass die Testdatei eine Datei ist, die vom Skript geschrieben wird. Richten Sie diesen Befehl nicht auf eine existierende Datei oder die existierende Datei wird mit zufälligen Daten überschrieben!

Für meine spezielle Hardware fand ich heraus, dass 128 KB die optimalste Eingangsblockgröße auf einer Festplatte und 32 KB die optimalste auf einer SSD war.

Obwohl diese Antwort die meisten meiner Erkenntnisse abdeckt, bin ich oft genug auf diese Situation gestoßen, dass ich einen Blog-Beitrag darüber geschrieben habe:http://blog.tdg5.com/tuning-dd-block-size/ Sie können weitere Einzelheiten finden auf die Tests, die ich dort durchgeführt habe.

Dieser StackOverflow-Beitrag kann auch hilfreich sein:dd:Wie berechnet man die optimale Blockgröße?


Linux
  1. Erste Schritte mit Samba für Interoperabilität

  2. Ausnahme wegen illegaler Blockgröße – CKR_ENCRYPTED_DATA_LEN_RANGE [SoftHSM]

  3. Unterschied zwischen Blockgröße und Clustergröße?

  4. Go For It – Eine moderne To-Do-Liste mit Timer

  5. Tauschen Sie die Partitionsgröße gegen 4 GB RAM aus

Linux-Gruppenbefehl für Anfänger (mit Beispielen)

Linux tr Command Tutorial für Anfänger (mit Beispielen)

Bash For Loop mit praktischen Beispielen

Youtube-dl Tutorial mit Beispielen für Anfänger

So finden Sie installierte Anwendungen mit installierter Größe in Linux

Das fc Command Tutorial mit Beispielen für Anfänger