Rendimiento de escritura abysmal general dm-crypt (LUKS)

21

Estoy investigando un problema en el que cifrar un dispositivo de bloque impone una gran penalización de rendimiento al escribir en él. Horas de lectura y experimentos en Internet no me proporcionaron una comprensión adecuada, y mucho menos una solución.

La pregunta en resumen: ¿por qué obtengo velocidades de escritura perfectamente rápidas cuando pongo un btrfs en un dispositivo de bloque (~ 170MB / s), mientras que la velocidad de escritura cae en picada (~ 20MB / s) cuando pongo un dm-crypt / LUKS entre sistema de archivos y el dispositivo de bloque, aunque el sistema es más que capaz de mantener un rendimiento de cifrado suficientemente alto?

Guión

/home/schlimmchen/randomes un archivo de 4.0GB lleno de datos de /dev/urandomantes.

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

Leerlo es súper rápido:

$ 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

(la segunda vez, el archivo obviamente se leyó del caché).

Btrfs sin cifrar

El dispositivo está formateado directamente con btrfs (sin tabla de particiones en el dispositivo de bloque).

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

La velocidad de escritura llega a ~ 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

La velocidad de lectura está muy por encima de 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

Btrfs cifrados en el dispositivo de bloque

El dispositivo está formateado con LUKS, y el dispositivo resultante está formateado con 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

La velocidad de lectura sufre solo marginalmente (¿por qué lo hace en absoluto?):

$ 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 cifrados en el archivo en btrfs en el dispositivo de bloque

La velocidad de escritura "se dispara" a más de 150 MB / s cuando se escribe en un archivo cifrado. Puse un btrfs en el dispositivo de bloque, asigné un archivo de 16GB, que edité y monté 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

¿Por qué aumenta el rendimiento de escritura de esta manera? ¿Qué logra este anidamiento particular de sistemas de archivos y dispositivos de bloque para ayudar en altas velocidades de escritura?

Preparar

El problema es reproducible en dos sistemas que ejecutan la misma distribución y kernel. Sin embargo, también observé las bajas velocidades de escritura con el kernel 3.19.0 en System2.

  • Dispositivo: SanDisk Extreme 64GB USB3.0 USB Stick
  • Sistema1: Intel NUC 5i5RYH, i5-5250U (Broadwell), 8GB RAM, Samsung 840 EVO 250GB SSD
  • Sistema2: Lenovo T440p, i5-4300M (Haswell), 16GB RAM, Samsung 850 PRO 256GB SSD
  • Distro / Kernel: Debian Jessie, 3.16.7
  • cryptsetup: 1.6.6
  • /proc/cryptopara System1: http://pastebin.com/QUSGMfiS
  • cryptsetup benchmarkpara System1: http://pastebin.com/4RxzPFeT
  • btrfs (-tools) es la versión 3.17
  • lsblk -t /dev/sdf: http://pastebin.com/nv49tYWc

Pensamientos

  • La alineación no es la causa por lo que puedo ver. Incluso si el tamaño de página del dispositivo es de 16 KB, el inicio de la carga útil de cryptsetup está alineado a 2 Mb de todos modos.
  • --allow-discards (para crykssetup's luksOpen) no ayudó, como esperaba.
  • Mientras hacía muchos menos experimentos con él, observé un comportamiento muy similar con un disco duro externo, conectado a través de un adaptador USB3.0.
  • Me parece que el sistema está escribiendo bloques de 64 KB. Un script de systemtrap que probé indica que al menos eso. /sys/block/sdf/statrespalda esta hipótesis, ya que muchas escrituras se fusionan. Entonces, supongo que escribir en bloques demasiado pequeños no es la causa.
  • No hubo suerte con cambiar el planificador de la cola del dispositivo de bloque a NOOP.
  • Poner la cripta en un volumen LVM no ayudó.
Schlimmchen
fuente
Borrar el caché del disco antes de cada prueba lo eliminaría como una posible razón para la velocidad (648 MB / s suena inalcanzable actualmente, fuera del RAM)
Xen2050

Respuestas:

18

La respuesta (como ahora sé): concurrencia .

En resumen : mi escritura secuencial , ya sea usando ddo al copiar un archivo (como ... en uso diario), se convierte en una escritura pseudoaleatoria (mala) porque cuatro hilos están trabajando simultáneamente para escribir los datos cifrados en el dispositivo de bloque después de concurrente cifrado (bueno).

Mitigación (para núcleos "antiguos")

El efecto negativo puede mitigarse aumentando la cantidad de solicitudes en cola en la cola del planificador de E / S de esta manera:

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

En mi caso, esto casi se triplica (~ 56MB / s) el rendimiento para la prueba de datos aleatorios de 4GB explicada en mi pregunta. Por supuesto, el rendimiento aún se queda corto de 100 MB / s en comparación con IO sin cifrar.

Investigación

Multinúcleo blktrace

Investigué aún más el escenario problemático en el que se coloca un btrfs en la parte superior de un dispositivo de bloque cifrado LUKS. Para mostrarme qué instrucciones de escritura se emiten al dispositivo de bloqueo real, utilicé blktraceasí:

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

Lo que esto hace es (por lo que pude comprender) rastrear la solicitud de E / S a la /dev/sdcque son de tipo " escribir ", luego analizar esto a salida legible por humanos pero restringir aún más la salida a la acción " D ", que es (según man blkparse) " IO emitido al conductor ".

El resultado fue algo como esto (ver aproximadamente 5000 líneas de salida del registro multinúcleo ):

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]
  • Columna 1: mayor, menor del dispositivo de bloque
  • Columna 2: ID de CPU
  • Columna 3: número de secuencia
  • Columna 4: sello de tiempo
  • Columna 5: ID del proceso
  • Columna 6: acción
  • Columna 7: datos RWBS (tipo, sector, longitud)

Esto es un recorte de la salida producida al ddincorporar los datos aleatorios de 4GB en el sistema de archivos montado. Está claro que al menos dos procesos están involucrados. El registro restante muestra que los cuatro procesadores realmente están trabajando en él. Lamentablemente, las solicitudes de escritura ya no se ordenan. Mientras CPU0 escribe en algún lugar alrededor del sector 38038416, CPU1, que está programado después, escribe en algún lugar alrededor del sector 35713872. Eso es malo.

Núcleo simple blktrace

Hice el mismo experimento después de deshabilitar subprocesos múltiples y deshabilitar el segundo núcleo de mi CPU. Por supuesto, solo un procesador participa en la escritura en el dispositivo. Pero lo que es más importante, la solicitud de escritura es propiamente secuencial, por lo que el rendimiento completo de escritura de ~ 170 MB / s se logra en la misma configuración.

Eche un vistazo a aproximadamente 5000 líneas de salida en el registro de un solo núcleo .

Discusión

Ahora que conozco la causa y los términos de búsqueda de Google adecuados, la información sobre este problema está surgiendo a la superficie. Resulta que no soy el primero en notarlo.

Corregido en los núcleos actuales (> = 4.0.2)

Como (más tarde) encontré que la confirmación del kernel obviamente estaba dirigida a este problema exacto, quería probar un kernel actualizado. [Después de compilarlo yo mismo y luego descubrir que ya está en debian/sid] Resulta que el problema está solucionado. No sé la versión exacta del núcleo en la que apareció la corrección, pero la confirmación original dará pistas a cualquier persona interesada.

Para el registro:

$ 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

Una punta de sombrero para Mikulas Patocka, quien escribió el commit.

Schlimmchen
fuente
1
Estoy usando btrfs en luks con el kernel 4.12.12 y la desaceleración sigue ahí.
brauliobo
¿Por qué dices que la desaceleración sigue ahí? ¿Qué referencia estás usando para no experimentar una desaceleración? ¿Cuál es tu configuración? ¿comprobaste el rendimiento de la unidad cuando solo eliminabas LUKS?
schlimmchen
confirmó que todavía está relacionado con LUKS unix.stackexchange.com/a/393521/39985
brauliobo
1
Ahora entiendo por qué escribirías sobre seguir experimentando una "desaceleración". Sin embargo, su problema está simplemente relacionado con este, definitivamente no es el mismo problema (retraso versus bajo rendimiento). ¡Experimento estas molestas molestias también, así que estoy muy agradecido de que hayas señalado tu problema aquí! No usar LUKS no es una opción, pero es bueno saber que parece estar relacionado con la causa.
schlimmchen