dd: Optimal blok boyutu nasıl hesaplanır? [kapalı]


122

A çalıştırırken en uygun blok boyutunu nasıl hesaplarsınız dd? Biraz araştırdım ve bunun nasıl başarılacağına dair hiçbir şey bulamadım.

Daha büyük bir blok boyutunun daha hızlı sonuçlanacağı izlenimine kapılıyorum dd... bu doğru mu?

Ben yaklaşık olduğum ddiki özdeş 500gb Hitachi HDD ben kullanımına blok-anlamaya çalışıyorum bu yüzden, 4GB DDR3 1333 mhz RAM Intel Core i3 çalıştıran bir kutuyu 7200rpm de koşmak. (Ubuntu 10.10 x86'yı bir flash sürücüden başlatacağım ve buradan çalıştıracağım.)


MacOS için @ tdg5 yanıtı kabul edildi - macos_dd_ibs_test.sh ve macos_dd_obs_test.sh
mixel

1
en iyi yanıt dd, dosyayı aktarırken en uygun blok boyutunu bulmaya yönelik bir özelliğe katkıda bulunmaktır
Boris

Bu neden konu dışı olarak işaretlendi ve süper kullanıcıya taşınmadı?
user267092

Yanıtlar:


95

En uygun blok boyutu, işletim sistemi (ve sürümü) ve ilgili çeşitli donanım veri yolları ve diskler dahil olmak üzere çeşitli faktörlere bağlıdır. Birkaç Unix benzeri sistem (Linux ve en azından bazı BSD türleri dahil) , çekirdeğin optimal blok boyutu olduğunu düşündüğü şeyi veren st_blksizeüyeyi tanımlar struct stat:

#include <sys/stat.h>
#include <stdio.h>

int main(void)
{
    struct stat stats;

    if (!stat("/", &stats))
    {
        printf("%u\n", stats.st_blksize);
    }
}

En iyi yol deneme yapmak olabilir: çeşitli blok boyutları ve zamanı olan bir gigabayt kopyalayın. (Her çalıştırmadan önce çekirdek arabelleği önbelleklerini temizlemeyi unutmayın :) echo 3 > /proc/sys/vm/drop_caches.

Bununla birlikte, genel bir kural olarak, yeterince büyük bir blok boyutunun ddiyi bir iş çıkarmasını sağladığını ve diyelim ki 64 KiB ile 1 MiB arasındaki farkların 4 KiB'ye karşı 64 KiB'ye kıyasla küçük olduğunu buldum. (Yine de, itiraf etmeliyim ki, bunu yaptığımdan bu yana epey zaman geçti. Şimdi varsayılan olarak bir mebibayt kullanıyorum veya sadece ddboyutu seçmeme izin veriyorum .)


11
Bunu cevap olarak asla kabul etmediğim için çok üzgünüm ... teşekkürler!
eckza

Önbellekleri bırakmayı hatırlamanın mükemmel bir noktası. Bu ölçümlerimi bozuyordu! (Küçük bir sorun olmasına rağmen: alt çizgi ile "drop_caches". Görünüşe göre düzenlemelerin en az 6 karakter olması gerekiyor ... :()
Tom

73

Diğerlerinin de söylediği gibi, evrensel olarak doğru blok boyutu yoktur; bir durum için en uygun olanı veya bir donanım parçası bir başkası için son derece verimsiz olabilir. Ayrıca, disklerin sağlığına bağlı olarak, "optimal" olandan farklı bir blok boyutu kullanmak tercih edilebilir.

Modern donanımda oldukça güvenilir olan bir şey, 512 baytlık varsayılan blok boyutunun, daha uygun bir alternatiften neredeyse bir kat daha yavaş olma eğiliminde olmasıdır. Şüphe duyduğumda, 64K'nın oldukça sağlam bir modern varsayılan olduğunu buldum. 64K genellikle en uygun blok boyutu olmasa da, deneyimlerime göre varsayılandan çok daha verimli olma eğilimindedir. 64K ayrıca güvenilir bir performans sergileme konusunda oldukça sağlam bir geçmişe sahiptir: 2002 civarında Eug-Lug posta listesinden 64K blok boyutu öneren bir mesaj bulabilirsiniz: http://www.mail-archive.com/eug- lug@efn.org/msg12073.html

En uygun çıktı bloğu boyutunu belirlemek için, varsayılan 512 bayttan maksimum 64M'ye kadar farklı blok boyutlarında dd ile 128M'lik bir test dosyası yazmayı test eden aşağıdaki komut dosyasını yazdım. Dikkat edin, bu komut dosyası dahili olarak dd kullanır, bu nedenle dikkatli kullanın.

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

GitHub'da görüntüle

Bu komut dosyasını yalnızca bir Debian (Ubuntu) sisteminde ve OSX Yosemite'de test ettim, bu nedenle diğer Unix çeşitleri üzerinde çalışmak için muhtemelen biraz ince ayar yapmak gerekecek.

Komut, varsayılan olarak geçerli dizinde dd_obs_testfile adlı bir test dosyası oluşturacaktır . Alternatif olarak, komut dosyası adından sonra bir yol sağlayarak özel bir test dosyasına giden bir yol sağlayabilirsiniz:

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

Komut dosyasının çıktısı, test edilen blok boyutlarının ve bunlara ait aktarım hızlarının bir listesidir:

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

(Not: Aktarım hızlarının birimi işletim sistemine göre değişecektir)

Optimum okuma bloğu boyutunu test etmek için, aşağı yukarı aynı işlemi kullanabilirsiniz, ancak / dev / zero'dan okumak ve diske yazmak yerine, diskten okuyup / dev / null'a yazarsınız. Bunu yapmak için bir komut dosyası şöyle görünebilir:

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

GitHub'da görüntüle

Bu durumda önemli bir fark, test dosyasının komut dosyası tarafından yazılan bir dosya olmasıdır. Bu komutu mevcut bir dosyaya doğrultmayın, aksi takdirde mevcut dosyanın üzerine sıfırlar yazılır!

Özel donanımım için, 128K'nın bir HDD'de en uygun giriş bloğu boyutu olduğunu ve 32K'nın bir SSD'de en uygun olduğunu buldum.

Bu cevap bulgularımın çoğunu kapsasa da, bu durumla ilgili bir blog yazısı yazdığım için yeterince zaman karşılaştım: http://blog.tdg5.com/tuning-dd-block-size/ Daha fazla ayrıntı bulabilirsiniz orada yaptığım testlerde.


1
512G SSD ile 2015 rMBP'de okuma performansını test ederek ikinci komut dosyasını çalıştırdım. En iyi blok boyutu 8388608: 3.582 GB bayt / sn idi.
Quinn Comendant

1
DÜZELTME: İkinci komut dosyasını çalıştırarak okuma performansını test ediyorum, 512 GB SSD ile 2015 rMBP'de. En iyi blok boyutu 524288 idi (5,754 GB / sn). İkinci en iyi blok boyutu 131072'dir (5,133 GB / sn). (Son yorumum için değerler oluştururken sonuçları yanlış sıraladım.)
Quinn Comendant

İçin dd_obs_test.sh conv=fsyncMacOS çalışmıyor ve kaldırılabilir.
rynop

Deneyimlerime göre, daha büyük blok boyutlarının karşılaştırılmasının doğru olması için daha büyük bir örneğe ihtiyacı var (birkaç saniye. Sanırım 128MB'lık bir dosya bunu yapmalı ama emin değilim). Emin değilim neden.
Rolf

2
Kanka! Ne harika bir cevap. Bu bir altın madeni bulmak, bir ton kir kazmak ve ardından istediğim ALTIN ​​NUGGET'i bulmak için işlemek gibidir: 64K Çok teşekkürler.
SDsolar

10

En uygun blok boyutumun 8 MB olduğunu buldum (disk önbelleğine eşit mi?) Sıkıştırılmış bir görüntüsünü oluşturmadan önce diskteki boş alanı silmem (bazıları şöyle der: yıkayın). Kullandım:

cd /media/DiskToWash/
dd if=/dev/zero of=zero bs=8M; rm zero

4K'dan 100M'ye kadar değerleri denedim.

Bir süre dd'nin çalışmasına izin verdikten sonra onu öldürdüm (Ctlr + C) ve çıktıyı okudum:

36+0 records in
36+0 records out
301989888 bytes (302 MB) copied, 15.8341 s, 19.1 MB/s

Dd girdi / çıktı oranını (bu durumda 19,1 MB / sn) gösterdiğinden, seçtiğiniz değerin öncekinden daha iyi mi yoksa daha kötü mü performans gösterdiğini görmek kolaydır.

Puanlarım:

bs=   I/O rate
---------------
4K    13.5 MB/s
64K   18.3 MB/s
8M    19.1 MB/s <--- winner!
10M   19.0 MB/s
20M   18.6 MB/s
100M  18.6 MB/s   

Not: Disk önbelleğinizin / arabellek boyutunuzun ne olduğunu kontrol etmek için şunu kullanabilirsiniz: sudo hdparm -i /dev/sda


4
Her testi yalnızca bir kez mi çalıştırdınız? Bence -64K'dan görebileceğiniz şey, arabellek zaten dolu ve fark sadece rastgele varyans.
Mads Y

Bir kez büyük değerlerin sistemi tıkayabileceğini duydum. Kişi büyük bir dosyayla çalışıyordu. Bunun hakkında daha fazla şey duysam iyi olur.
Todd Partridge

1
Benim deneyimim de yenmenin 8Mzor olduğunu gösteriyor .
Sridhar Sarnobat

İlginç. Bunun L3 önbellek boyutuyla ilgili olduğunu düşünüyor musunuz? L3 önbelleğinden daha büyük blok boyutlarının daha yavaş olup olmayacağını merak ediyorum.
SurpriseDog

3

Bu tamamen sisteme bağlıdır. En uygun çözümü bulmak için denemelisiniz. İle başlamayı deneyin bs=8388608. (Hitachi HDD'lerinde 8MB önbellek olduğu görülüyor.)


5
birçok dd sürümü kısayolları kabul eder: yani bs=8MGNU / Linux veya bs=8mBSD üzerinde
pascal

4
lol, "Şundan başlamayı dene bs=8388608 Her adımda ve
azaltmayı dene

1
  • Daha iyi performans için RAM'in alabileceği en büyük blok boyutunu kullanın (işletim sistemine daha az I / O çağrısı gönderir)
  • daha iyi doğruluk ve veri kurtarma için blok boyutunu girdinin yerel sektör boyutuna ayarlayın

Dd, veriyi conv = noerror, sync seçeneğiyle kopyaladığından, karşılaştığı herhangi bir hata, bloğun geri kalanının sıfır baytlarla değiştirilmesine neden olur. Daha büyük blok boyutları daha hızlı kopyalanacaktır, ancak her hatayla karşılaşıldığında bloğun geri kalanı göz ardı edilir.

kaynak


1
Bence herhangi bir yazma hatası varsa, aracı değiştirmelisiniz, blok boyutunu değiştirmemelisiniz ...
unfa
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.