Abysmal general dm-crypt (LUKS) wydajność zapisu

21

Badam problem polegający na tym, że szyfrowanie urządzenia blokowego nakłada ogromną obniżkę wydajności podczas pisania na nim. Godziny czytania w Internecie i eksperymenty nie zapewniły mi właściwego zrozumienia, nie mówiąc już o rozwiązaniu.

Pytanie w skrócie: Dlaczego uzyskuję idealnie duże prędkości zapisu, gdy umieszczam btrfs na urządzeniu blokowym (~ 170 MB / s), podczas gdy prędkość zapisu spada (~ 20 MB / s), gdy umieszczamy dm-crypt / LUKS pomiędzy system plików i urządzenie blokujące, chociaż system jest w stanie utrzymać wystarczająco wysoką przepustowość szyfrowania?

Scenariusz

/home/schlimmchen/randomto plik 4,0 GB wypełniony /dev/urandomwcześniejszymi danymi .

dd if=/dev/urandom of=/home/schlimmchen/Documents/random bs=1M count=4096

Czytanie jest bardzo szybkie:

$ dd if=/home/schlimmchen/Documents/random of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 6.58036 s, 648 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 0.786102 s, 5.4 GB/s

(po raz drugi plik został oczywiście odczytany z pamięci podręcznej).

Nieszyfrowane btrfs

Urządzenie jest bezpośrednio formatowane przy pomocy btrfs (brak tablicy partycji na urządzeniu blokowym).

$ sudo mkfs.btrfs /dev/sdf
$ sudo mount /dev/sdf /mnt
$ sudo chmod 777 /mnt

Prędkość zapisu osiąga nawet ~ 170 MB / s:

$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 27.1564 s, 157 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test2 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 25.1882 s, 169 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test3 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 29.8419 s, 143 MB/s

Szybkość odczytu jest znacznie powyżej 200 MB / s.

$ dd if=/mnt/dd-test1 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.8265 s, 215 MB/s
$ dd if=/mnt/dd-test2 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.9821 s, 213 MB/s
$ dd if=/mnt/dd-test3 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.8561 s, 215 MB/s

Zaszyfrowane btrfs na urządzeniu blokowym

Urządzenie jest sformatowane za pomocą LUKS, a powstałe urządzenie jest sformatowane za pomocą btrfs:

$ sudo cryptsetup luksFormat /dev/sdf
$ sudo cryptsetup luksOpen /dev/sdf crypt
$ sudo mkfs.btrfs /dev/mapper/crypt
$ sudo mount /dev/mapper/crypt /mnt
$ sudo chmod 777 /mnt
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 210.42 s, 20.3 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test2 bs=1M 
4265841146 bytes (4.3 GB) copied, 207.402 s, 20.6 MB/s

Prędkość odczytu cierpi tylko nieznacznie (dlaczego w ogóle?):

$ dd if=/mnt/dd-test1 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 22.2002 s, 192 MB/s
$ dd if=/mnt/dd-test2 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 22.0794 s, 193 MB/s

luksDump: http://pastebin.com/i9VYRR0p

Zaszyfrowane pliki btrfs w pliku na btrfs na urządzeniu blokowym

Prędkość zapisu „gwałtownie rośnie” do ponad 150 MB / s przy zapisie do zaszyfrowanego pliku. Umieściłem btrfs na urządzeniu blokowym, przydzieliłem plik 16 GB, który lukfsFormatzredagowałem i zamontowałem.

$ sudo mkfs.btrfs /dev/sdf -f
$ sudo mount /dev/sdf /mnt
$ sudo chmod 777 /mnt
$ dd if=/dev/zero of=/mnt/crypted-file bs=1M count=16384 conv=fsync
17179869184 bytes (17 GB) copied, 100.534 s, 171 MB/s
$ sudo cryptsetup luksFormat /mnt/crypted-file
$ sudo cryptsetup luksOpen /mnt/crypted-file crypt
$ sudo mkfs.btrfs /dev/mapper/crypt
$ sudo mount /dev/mapper/crypt /tmp/nested/
$ dd if=/home/schlimmchen/Documents/random of=/tmp/nested/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 26.4524 s, 161 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/tmp/nested/dd-test2 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 27.5601 s, 155 MB/s

Dlaczego wydajność zapisu rośnie w ten sposób? Co osiąga to szczególne zagnieżdżanie systemów plików i urządzeń blokowych, aby pomóc w wysokich prędkościach zapisu?

Ustawiać

Problem można odtworzyć w dwóch systemach z tą samą dystrybucją i jądrem. Jednak zaobserwowałem również niskie prędkości zapisu w jądrze 3.19.0 na System2.

  • Urządzenie: pamięć USB SanDisk Extreme 64 GB USB 3.0
  • System1: Intel NUC 5i5RYH, i5-5250U (Broadwell), 8 GB pamięci RAM, Samsung 840 EVO 250 GB SSD
  • System2: Lenovo T440p, i5-4300M (Haswell), 16 GB pamięci RAM, Samsung 850 PRO 256 GB SSD
  • Distro / Kernel: Debian Jessie, 3.16.7
  • cryptsetup: 1.6.6
  • /proc/cryptodla System1: http://pastebin.com/QUSGMfiS
  • cryptsetup benchmarkdla System1: http://pastebin.com/4RxzPFeT
  • btrfs (-tools) to wersja 3.17
  • lsblk -t /dev/sdf: http://pastebin.com/nv49tYWc

Myśli

  • O ile wiem, wyrównanie nie jest przyczyną. Nawet jeśli rozmiar strony kija wynosi 16 kB, początkowy ładunek szyfrowania jest i tak wyrównany do 2 MB.
  • --allow-discards (dla luksOpen cryptsetup) nie pomogło, jak się spodziewałem.
  • Robiąc z nim o wiele mniej eksperymentów, zaobserwowałem bardzo podobne zachowanie z zewnętrznym dyskiem twardym podłączonym przez adapter USB 3.0.
  • Wydaje mi się, że system zapisuje bloki 64 KB. Skrypt systemtrap Próbowałem wskazuje, że przynajmniej. /sys/block/sdf/statpopiera tę hipotezę, ponieważ wiele zapisów jest scalonych. Domyślam się więc, że pisanie zbyt małymi blokami nie jest przyczyną.
  • Brak powodzenia w zmianie harmonogramu kolejki urządzeń blokowych na NOOP.
  • Umieszczenie krypty w woluminie LVM nie pomogło.
schlimmchen
źródło
Wyczyszczenie pamięci podręcznej dysku przed każdym testem wyeliminuje ją jako możliwy powód szybkości (obecnie 648 MB / s wydaje się nieosiągalne poza
ramem

Odpowiedzi:

18

Odpowiedź (jak teraz wiem): współbieżność .

W skrócie : Mój sekwencyjny zapis , przy użyciu ddlub podczas kopiowania pliku (jak ... w codziennym użyciu), staje się pseudolosowym zapisem (zły), ponieważ cztery wątki pracują jednocześnie przy zapisie zaszyfrowanych danych na urządzeniu blokowym po równoczesnym szyfrowanie (dobre).

Łagodzenie (dla „starszych” jąder)

Negatywny efekt można złagodzić, zwiększając liczbę żądań w kolejce w kolejce harmonogramu We / Wy w następujący sposób:

echo 4096 | sudo tee /sys/block/sdc/queue/nr_requests

W moim przypadku prawie trzykrotnie (~ 56 MB / s) przepustowość losowego testu danych 4 GB wyjaśniona w moim pytaniu. Oczywiście wydajność wciąż nie przekracza 100 MB / s w porównaniu do nieszyfrowanego IO.

Dochodzenie

Wielordzeniowy blktrace

Dalej zbadałem problematyczny scenariusz, w którym btrfs jest umieszczony na górze urządzenia blokowego szyfrowanego LUKS. Aby pokazać mi, jakie instrukcje zapisu są wysyłane do rzeczywistego urządzenia blokowego, użyłem blktracetego w następujący sposób:

sudo blktrace -a write -d /dev/sdc -o - | blkparse -b 1 -i - | grep -w D

To, co robi, to (o ile mogłem to zrozumieć) śledzić żądanie We / Wy, do /dev/sdcktórego są typu „ zapisz ”, a następnie parsować je do danych wyjściowych czytelnych dla ludzi, ale dodatkowo ograniczyć dane wyjściowe do działania „ D ”, które jest (zgodnie z man blkparse) „ IO wydane kierowcy ”.

Wynik był mniej więcej taki (patrz około 5000 wierszy danych wyjściowych dziennika wielordzeniowego ):

8,32   0    32732   127.148240056     3  D   W 38036976 + 240 [ksoftirqd/0]
8,32   0    32734   127.149958221     3  D   W 38038176 + 240 [ksoftirqd/0]
8,32   0    32736   127.160257521     3  D   W 38038416 + 240 [ksoftirqd/0]
8,32   1    30264   127.186905632    13  D   W 35712032 + 240 [ksoftirqd/1]
8,32   1    30266   127.196561599    13  D   W 35712272 + 240 [ksoftirqd/1]
8,32   1    30268   127.209431760    13  D   W 35713872 + 240 [ksoftirqd/1]
  • Kolumna 1: główna, niewielka część urządzenia blokowego
  • Kolumna 2: ID procesora
  • Kolumna 3: numer kolejny
  • Kolumna 4: znacznik czasu
  • Kolumna 5: identyfikator procesu
  • Kolumna 6: działanie
  • Kolumna 7: Dane RWBS (typ, sektor, długość)

Jest to wycinek danych wyjściowych wygenerowanych podczas ddzapisywania losowych danych 4 GB na zamontowanym systemie plików. Oczywiste jest, że w grę wchodzą co najmniej dwa procesy. Pozostały dziennik pokazuje, że wszystkie cztery procesory faktycznie nad nim pracują. Niestety, prośby o zapis nie są już zamawiane. Podczas gdy CPU0 pisze gdzieś w okolicach 38038416. sektora, CPU1, który jest zaplanowany później, pisze gdzieś w okolicach 35713872. sektora. To źle.

Pojedynczy rdzeń blktrace

Zrobiłem ten sam eksperyment po wyłączeniu wielowątkowości i wyłączeniu drugiego rdzenia mojego procesora. Oczywiście tylko jeden procesor jest zaangażowany w pisanie na patyku. Co ważniejsze, żądanie zapisu jest odpowiednio sekwencyjne, dlatego pełną wydajność zapisu ~ 170 MB / s uzyskuje się w tej samej konfiguracji.

Spójrz na około 5000 wierszy danych wyjściowych w dzienniku singlecore .

Dyskusja

Teraz, gdy znam przyczynę i odpowiednie wyszukiwane hasła w Google, informacje o tym problemie pojawiają się na powierzchni. Jak się okazuje, nie jestem pierwszym, który to zauważa.

Naprawiono w obecnych jądrach (> = 4.0.2)

Ponieważ (później) odkryłem, że zatwierdzenie jądra jest wyraźnie ukierunkowane na ten właśnie problem, chciałem wypróbować zaktualizowane jądro. [Po samodzielnym skompilowaniu i odkryciu, że już jest w środku debian/sid] Okazuje się, że problem rzeczywiście został rozwiązany. Nie znam dokładnej wersji jądra, w której pojawiła się poprawka, ale oryginalne zatwierdzenie da wskazówki wszystkim zainteresowanym.

Dla przypomnienia:

$ uname -a
Linux t440p 4.0.0-1-amd64 #1 SMP Debian 4.0.2-1 (2015-05-11) x86_64 GNU/Linux
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test bs=1M conv=fsync
4294967296 bytes (4.3 GB) copied, 29.7559 s, 144 MB/s

Czapka dla Mikulasa Patockiego, który jest autorem commitu.

schlimmchen
źródło
1
Używam btrfs na Luksie z jądrem 4.12.12, a spowolnienie wciąż trwa!
brauliobo
dlaczego mówicie, że spowolnienie nadal istnieje? z jakich referencji korzystasz, więc nie wystąpiło spowolnienie? jaka jest twoja konfiguracja? czy sprawdziłeś wydajność napędu tylko podczas usuwania LUKS?
schlimmchen
potwierdzono, że nadal jest powiązany z LUKS unix.stackexchange.com/a/393521/39985
brauliobo 20.09.17
1
Teraz rozumiem, dlaczego piszesz o tym, że wciąż doświadczasz „spowolnienia”. Jednak twój problem jest tylko z tym związany, zdecydowanie nie jest to ten sam problem (opóźnienie w stosunku do niskiej wydajności). Doświadczam także tych irytujących czkawek, dlatego jestem bardzo wdzięczny, że zwrócił pan uwagę na swój problem! Nieużywanie LUKS nie jest opcją, ale dobrze wiedzieć, że wydaje się, że jest to związane z przyczyną.
schlimmchen