Czy opcja „bs” w „dd” naprawdę poprawia prędkość?

58

Od czasu do czasu mówiono mi, że aby zwiększyć szybkość „dd”, powinienem starannie wybrać odpowiedni „rozmiar bloku”.

Nawet tutaj, na ServerFault, ktoś inny napisał, że „ … optymalny rozmiar bloku zależy od sprzętu…(iain) lub „ … idealny rozmiar zależy od magistrali systemowej, kontrolera dysku twardego, konkretnego napędu i sterowniki dla każdego z nich ...(Chris-s)

Ponieważ moje odczucia były nieco inne ( BTW: Myślałem, że czas potrzebny do dogłębnego dostrojenia parametru bs był znacznie wyższy niż otrzymany zysk, pod względem zaoszczędzonego czasu i że domyślnie było rozsądne ), dzisiaj po prostu poszedłem poprzez szybkie i brudne testy.

Aby zmniejszyć wpływy zewnętrzne, postanowiłem przeczytać:

  • z zewnętrznej karty MMC
  • z wewnętrznej partycji

i:

  • z podłączonymi systemami plików
  • wysyłanie danych wyjściowych do / dev / null, aby uniknąć problemów związanych z „szybkością zapisu”;
  • unikanie podstawowych problemów związanych z buforowaniem dysku twardego, przynajmniej w przypadku korzystania z dysku twardego.

W poniższej tabeli przedstawiłem swoje wyniki, czytając 1 GB danych o różnych wartościach „bs” ( surowe liczby można znaleźć na końcu tej wiadomości ):

wprowadź opis zdjęcia tutaj

Zasadniczo okazuje się, że:

  • MMC: przy bs = 4 (tak! 4 bajty) osiągnąłem przepustowość 12 MB / s. Nie tak odległe wartości wrt do maksimum 14,2 / 14,3, które otrzymałem od bs = 5 i więcej;

  • HDD: przy bs = 10 osiągnąłem 30 MB / s. Z pewnością niższy niż 95,3 MB, przy domyślnym bs = 512, ale ... także znaczącym.

Było również bardzo jasne, że czas sys procesora był odwrotnie proporcjonalny do wartości bs (ale brzmi to rozsądnie, ponieważ im niższy bs, tym większa liczba wywołań sys generowanych przez dd).

Powiedziawszy to wszystko, teraz pytanie: czy ktoś może wyjaśnić (haker jądra?), Jakie są główne komponenty / systemy zaangażowane w taką przepustowość i czy naprawdę warto wysiłek w określeniu bs wyższej niż domyślna?


Obudowa MMC - liczby surowe

bs = 1 M.

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1M count=1000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 74,1239 s, 14,1 MB/s

real    1m14.126s
user    0m0.008s
sys     0m1.588s

bs = 1k

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1k count=1000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,7795 s, 14,1 MB/s

real    1m12.782s
user    0m0.244s
sys     0m2.092s

bs = 512

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=512 count=2000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,867 s, 14,1 MB/s

real    1m12.869s
user    0m0.324s
sys     0m2.620s

bs = 10

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,1662 s, 14,3 MB/s

real    1m10.169s
user    0m6.272s
sys     0m28.712s

bs = 5

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,415 s, 14,2 MB/s

real    1m10.417s
user    0m11.604s
sys     0m55.984s

bs = 4

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 80,9114 s, 12,4 MB/s

real    1m20.914s
user    0m14.436s
sys     1m6.236s

bs = 2

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 161,974 s, 6,2 MB/s

real    2m41.976s
user    0m28.220s
sys     2m13.292s

bs = 1

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 325,316 s, 3,1 MB/s

real    5m25.318s
user    0m56.212s
sys     4m28.176s

Obudowa dysku twardego - liczby surowe

bs = 1

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 341,461 s, 2,9 MB/s

real    5m41.463s
user    0m56.000s
sys 4m44.340s

bs = 2

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 164,072 s, 6,1 MB/s

real    2m44.074s
user    0m28.584s
sys 2m14.628s

bs = 4

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 81,471 s, 12,3 MB/s

real    1m21.473s
user    0m14.824s
sys 1m6.416s

bs = 5

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 66,0327 s, 15,1 MB/s

real    1m6.035s
user    0m11.176s
sys 0m54.668s

bs = 10

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 33,4151 s, 29,9 MB/s

real    0m33.417s
user    0m5.692s
sys 0m27.624s

bs = 512 (przesunięcie odczytu, aby uniknąć buforowania)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=512 count=2000000 skip=6000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,7437 s, 95,3 MB/s

real    0m10.746s
user    0m0.360s
sys 0m2.428s

bs = 1k (przesunięcie odczytu, aby uniknąć buforowania)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1k count=1000000 skip=6000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,6561 s, 96,1 MB/s

real    0m10.658s
user    0m0.164s
sys 0m1.772s

bs = 1k (przesunięcie odczytu, aby uniknąć buforowania)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1M count=1000 skip=7000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 10,7391 s, 97,6 MB/s

real    0m10.792s
user    0m0.008s
sys 0m1.144s
Damiano Verzulli
źródło
11
To, co byłoby naprawdę miłe, to mieć bs=autofunkcję dd, która wykryje i użyje optymalnego parametru bs z urządzenia.
4
Niezwykle przyjemny byłby wykres kilku bsrozmiarów wykreślony w funkcji prędkości zamiast 15 tuzinów bloków kodu w jednym pytaniu. Zajmie mniej miejsca i będzie nieskończenie szybszy do czytania. Obraz naprawdę jest warty tysiące słów.
MDMoore313,
2
@BigHomie - zastanawiałem się nad udostępnieniem wykresu, ale ... istnieje kilka problemów związanych ze skalowaniem. Prawdopodobnie potrzebowałaby skali logarytmicznej na obu osiach i ... myśląc o tym, pomyślałem, że nie jest to łatwy (i szybki) problem do rozwiązania. Więc przełączyłem się na wersję „stołową”. Jeśli chodzi o „... 15 tuzin bloków kodu”, chciałem, aby każdy miał szansę sprawdzić „surowe liczby”, aby uniknąć jakichkolwiek (osobistych, moich) zakłóceń.
Damiano Verzulli,
1
@DamianoVerzulli stół jest fajny, proszę zignoruj ​​mój rant, i tak dałem ci głos za udowodnienie naszych przesądów i wiem z pierwszej ręki, że majstrowanie przy wielkości bajtów zmieni szybkość, mogę również odpowiedzieć.
MDMoore313,
1
@warren - aby uzyskać 4G, możesz także zrobić bs=8k count=512Klub bs=1M count=4Knie pamiętam potęg 2 z poprzednich 65536
użytkownik313114

Odpowiedzi:

24

To, co zrobiłeś, to tylko test prędkości odczytu. jeśli faktycznie kopiujesz bloki na inne urządzenie, masz przerwy w czytaniu, podczas gdy drugie urządzenie akceptuje dane, które chcesz zapisać, gdy tak się dzieje, możesz natrafić na problemy z opóźnieniami obrotowymi na czytanym urządzeniu (jeśli jest to dysk twardy) i tak dalej często znacznie szybciej jest odczytywać 1M fragmentów z dysku twardego, gdy rzadziej napotykasz opóźnienia rotacyjne.

Wiem, że kiedy kopiuję dyski twarde, uzyskuję większą szybkość, określając bs=1Mniż używając bs=4klub domyślnie. Mówię o poprawie prędkości od 30 do 300 procent. Nie ma potrzeby dostrajania go do absolutnego najlepszego, chyba że to wszystko, co robisz każdego dnia. ale wybranie czegoś lepszego niż domyślny może skrócić godziny wykonania.

Kiedy używasz go naprawdę, wypróbuj kilka różnych numerów i wyślij ddprocesowi SIGUSR1sygnał, aby wydał raport o stanie, abyś mógł zobaczyć, jak idzie.

✗ killall -SIGUSR1 dd
1811+1 records in
1811+1 records out
1899528192 bytes (1.9 GB, 1.8 GiB) copied, 468.633 s, 4.1 MB/s
użytkownik313114
źródło
2014 Macbook Pro Retina kopiowanie na pamięć USB3 o szybkości zapisu 90 MB / s: $ sudo dd if=~/Downloads/Qubes-R4.0-rc4-x86_64.iso of=/dev/rdisk2 status=progresspokazuje 6140928 bytes (6.1 MB, 5.9 MiB) copied, 23 s, 267 kB/s. Anulowałem to, ponieważ trwało to zbyt długo. Teraz określam wielkość bajtów: $ sudo dd if=~/Downloads/Qubes-R4.0-rc4-x86_64.iso of=/dev/rdisk2 bs=1M status=progresspokazuje4558159872 bytes (4.6 GB, 4.2 GiB) copied, 54 s, 84.4 MB/s
Eric Duncan
9

Przynajmniej jeśli chodzi o wewnętrzny dysk twardy - podczas odczytu z urządzenia warstwa blokowa musi przynajmniej pobrać jeden sektor, który ma 512 bajtów.

Tak więc, podczas obsługi odczytu 1-bajtowego tak naprawdę odczytujesz tylko z dysku pobierania wyrównanego do sektora bajtu. Pozostałe 511 razy jest obsługiwane przez pamięć podręczną.

Możesz to udowodnić w następujący sposób, w tym przykładzie interesujący sdbjest dysk:

# grep sdb /proc/diskstats
8      16 sdb 767 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...
# dd if=/dev/sdb of=/dev/null bs=1 count=512
512+0 records in
512+0 records out
512 bytes (512 B) copied, 0.0371715 s, 13.8 kB/s
# grep sedb /proc/diskstats
8      16 sdb 768 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...

Czwarta kolumna (która liczy odczyty) wskazuje, że wystąpił tylko 1 odczyt, mimo że zażądałeś 1 bajtu odczytu. Jest to oczekiwane zachowanie, ponieważ to urządzenie (dysk SATA 2) musi co najmniej zwracać rozmiar sektora. Jądro po prostu buforuje cały sektor.

Najważniejszym czynnikiem w tych żądaniach rozmiaru jest narzut związany z wydaniem wywołania systemowego w celu odczytu lub zapisu. W rzeczywistości wydanie wezwania dla <512 jest nieefektywne. Bardzo duże odczyty wymagają mniej wywołań systemowych kosztem większej ilości pamięci używanej do tego celu.

4096 to zazwyczaj „bezpieczny” numer do odczytu, ponieważ:

  • Podczas czytania z włączonym buforowaniem (domyślnie) strona ma rozmiar 4k. Wypełnianie strony odczytami <4k jest bardziej skomplikowane niż utrzymywanie tego samego odczytu i rozmiaru strony.
  • Większość rozmiarów bloków systemu plików jest ustawiona na 4k.
  • Nie jest to wystarczająco mała liczba (być może teraz dla dysków SSD), aby spowodować obciążenie systemowe, ale nie jest to wystarczająco duża liczba, aby zużywać dużo pamięci.
Matthew Ife
źródło