Бедный генерал dm-crypt (LUKS) пишет производительность

21

Я исследую проблему, когда шифрование блочного устройства приводит к огромным потерям производительности при записи на него. Часы чтения в Интернете и эксперименты не дали мне правильного понимания, не говоря уже о решении.

Короче вопрос: почему я получаю совершенно высокие скорости записи при помещении btrfs на блочное устройство (~ 170 МБ / с), в то время как скорость записи резко падает (~ 20 МБ / с) при установке dm-crypt / LUKS между файловая система и блочное устройство, хотя система более чем способна поддерживать достаточно высокую пропускную способность шифрования?

сценарий

/home/schlimmchen/randomфайл объемом 4,0 ГБ, заполненный данными из /dev/urandomпредыдущих

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

Чтение это супер быстро:

$ 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

(второй раз файл явно читался из кеша).

Незашифрованные btrfs

Устройство напрямую отформатировано с помощью btrfs (нет таблицы разделов на блочном устройстве).

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

Скорость записи достигает ~ 170 МБ / с:

$ 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

Скорость чтения значительно выше 200 МБ / с.

$ 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

Зашифрованные btrfs на блочном устройстве

Устройство отформатировано с помощью LUKS, а полученное устройство отформатировано с помощью 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

Скорость чтения страдает лишь незначительно (почему это вообще?):

$ 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

Зашифрованные btrfs в файле на btrfs на блочном устройстве

Скорость записи увеличивается до 150 МБ / с при записи в зашифрованный файл. Я поместил btrfs на блочное устройство, выделил файл 16 ГБ, который я lukfsFormatредактировал и монтировал.

$ 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

Почему производительность записи увеличивается так? Чего добивается эта конкретная вложенность файловых систем и блочных устройств для обеспечения высокой скорости записи?

Настроить

Проблема воспроизводима на двух системах, работающих под управлением одного и того же дистрибутива и ядра. Однако я также наблюдал низкие скорости записи с ядром 3.19.0 на System2.

  • Устройство: USB-накопитель SanDisk Extreme 64 ГБ USB3.0
  • Система 1: Intel NUC 5i5RYH, i5-5250U (Broadwell), 8 ГБ ОЗУ, Samsung 840 EVO, 250 ГБ SSD
  • Система2: Lenovo T440p, i5-4300M (Haswell), 16 ГБ ОЗУ, Samsung 850 PRO, 256 ГБ SSD
  • Дистрибутив / Ядро: Debian Jessie, 3.16.7
  • cryptsetup: 1.6.6
  • /proc/cryptoдля System1: http://pastebin.com/QUSGMfiS
  • cryptsetup benchmarkдля System1: http://pastebin.com/4RxzPFeT
  • btrfs (-tools) - версия 3.17
  • lsblk -t /dev/sdf: http://pastebin.com/nv49tYWc

мысли

  • Выравнивание не причина, насколько я вижу. Даже если размер страницы флешки составляет 16 КБ, начало полезной нагрузки cryptsetup в любом случае выравнивается до 2 МБ.
  • --allow-discards (для luksOpen cryptsetup) не помогло, как я ожидал.
  • Проводя с ним гораздо меньше экспериментов, я наблюдал очень похожее поведение с внешним жестким диском, подключенным через адаптер USB3.0.
  • Мне кажется, что система записывает блоки по 64 КБ. Systemtrap сценарий я попытался показывает , что по крайней мере. /sys/block/sdf/statподтверждает эту гипотезу, поскольку многие записи объединены. Таким образом, я предполагаю, что письмо в слишком маленьких блоках не является причиной.
  • Не повезло с изменением планировщика очереди блочных устройств на NOOP.
  • Помещение склепа в том LVM не помогло.
schlimmchen
источник
Очистка дискового кеша перед каждым тестом устранит его как возможную причину скорости (в настоящее время 648 МБ / с звучит недостижимо вне
рампы памяти

Ответы:

18

Ответ (как я теперь знаю): параллелизм .

Вкратце : моя последовательная запись с использованием ddили при копировании файла (например ... при ежедневном использовании) становится псевдослучайной записью (плохо), поскольку четыре потока одновременно работают над записью зашифрованных данных на блочное устройство после одновременной шифрование (хорошо).

Смягчение (для «старых» ядер)

Негативный эффект можно уменьшить, увеличив количество запросов в очереди в очереди планировщика ввода-вывода, например:

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

В моем случае это почти утроило (~ 56 МБ / с) пропускную способность для теста случайных данных 4 ГБ, объясненного в моем вопросе. Конечно, производительность по-прежнему ниже 100 МБ / с по сравнению с незашифрованным вводом-выводом.

изучение

многожильный blktrace

Кроме того, я исследовал проблемный сценарий, в котором btrfs помещается поверх зашифрованного блочного устройства LUKS. Чтобы показать мне, какие инструкции по записи выдаются фактическому блочному устройству, я использовал blktraceэто так:

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

Что это делает (насколько я смог понять), проследить запрос ввода-вывода, /dev/sdcкоторые имеют тип " запись », затем анализировать его для читабельного вывода, но далее ограничивать вывод действием « D », которое (согласно man blkparse) « IO выдан водителю ».

Результат был примерно таким (см. Около 5000 строк вывода многожильного журнала ):

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]
  • Колонка 1: мажор, минор блочного устройства
  • Колонка 2: идентификатор процессора
  • Колонка 3: порядковый номер
  • Колонка 4: отметка времени
  • Колонка 5: идентификатор процесса
  • Колонка 6: действие
  • Колонка 7: данные RWBS (тип, сектор, длина)

Это фрагмент выходных данных, полученных при записи ddслучайных данных 4 ГБ в смонтированную файловую систему. Понятно, что участвуют как минимум два процесса. Оставшийся журнал показывает, что все четыре процессора фактически работают над ним. К сожалению, запросы на запись больше не упорядочены. В то время как CPU0 записывает где-то около 38038416-го сектора, CPU1, который запланирован позже, записывает где-то около 35713872-го сектора. Плохо.

Singlecore blktrace

Я сделал тот же эксперимент после отключения многопоточности и отключения второго ядра моего процессора. Конечно, только один процессор участвует в записи на флешку. Но что еще более важно, запрос на запись является правильно последовательным, поэтому полная производительность записи ~ 170 МБ / с достигается в остальных случаях.

Посмотрите на около 5000 строк вывода в одноядерном журнале .

обсуждение

Теперь, когда я знаю причину и правильные условия поиска в Google, информация об этой проблеме всплывает на поверхность. Оказывается, я не первый, кто замечает.

Исправлено в текущих ядрах (> = 4.0.2)

Поскольку (позже) я обнаружил, что коммит ядра явно предназначен именно для этой проблемы, я хотел попробовать обновленное ядро. [После того, как он сам скомпилирован, а затем обнаружил, что он уже есть debian/sid] Оказывается, проблема действительно решена. Я не знаю точную версию ядра, в которой появилось исправление, но оригинальный коммит даст подсказки всем, кто заинтересован.

Для записи:

$ 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

Шляпная шапка Микулашу Патоцке, который написал коммит.

schlimmchen
источник
1
Я использую btrfs на Luks с ядром 4.12.12, и замедление все еще там!
Браулиобо
почему вы говорите, что замедление все еще там? какую ссылку вы используете, чтобы не испытывать замедления? каковы ваши настройки? Вы проверили производительность диска только при удалении LUKS?
schlimmchen
подтвердил, что это все еще связано с LUKS unix.stackexchange.com/a/393521/39985
brauliobo
1
Теперь я понимаю, почему вы пишете о том, что все еще испытываете «замедление». Тем не менее, ваша проблема просто связана с этим, это определенно не та же проблема (отставание или низкая производительность). Я действительно испытываю эти раздражающие всплески, так что я очень благодарен, что вы указали свою проблему здесь! Не использовать LUKS - это не вариант, но приятно знать, что это связано с причиной.
schlimmchen