Problema
Recientemente instalé un nuevo disco y creé un zpool en él:
/# zpool create morez /dev/sdb
Después de usarlo por un tiempo, noté que era bastante lento:
/morez# fio --name rw --rw rw --size 10G
read: IOPS=19.6k, BW=76.6MiB/s (80.3MB/s)(5120MiB/66834msec)
write: IOPS=19.6k, BW=76.6MiB/s (80.3MB/s)(5120MiB/66834msec)
Esta prueba es bastante similar a mi caso de uso real. Estoy leyendo un número moderado (~ 10k) de imágenes (~ 2 MiB cada una) del disco. Fueron escritos de una vez cuando el disco estaba casi vacío, por lo que no espero que estén fragmentados.
A modo de comparación, probé ext4:
/# gdisk /dev/sdb
...
/# mkfs.ext4 -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# fio --name rw --rw rw --size 10G
read: IOPS=48.3k, BW=189MiB/s (198MB/s)(5120MiB/27135msec)
write: IOPS=48.3k, BW=189MiB/s (198MB/s)(5120MiB/27135msec)
Y btrfs:
/# mkfs.btrfs -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# fio --name rw --rw rw --size 10G
read: IOPS=51.3k, BW=201MiB/s (210MB/s)(5120MiB/25528msec)
write: IOPS=51.3k, BW=201MiB/s (210MB/s)(5120MiB/25528msec)
¿Qué podría estar causando los problemas de rendimiento con ZFS y cómo puedo hacerlo más rápido?
Intento fallido de solución
También intenté establecer explícitamente el tamaño del sector para el zpool, ya que mi disco ( Seagate ST1000DM003 ) usa sectores físicos de 4096 bytes:
/# zpool create -o ashift=12 morez /dev/sdb
Esto no mejoró el rendimiento:
/morez# fio --name rw --rw rw --size 10G
read: IOPS=21.3k, BW=83.2MiB/s (87.2MB/s)(5120MiB/61573msec)
write: IOPS=21.3k, BW=83.2MiB/s (87.2MB/s)(5120MiB/61573msec)
Observación
Curiosamente, usar un zvol tuvo un gran rendimiento:
/# zfs create -V 20G morez/vol
/# fio --name rw --filename /dev/zvol/morez/vol --rw rw --size 10G
read: IOPS=52.7k, BW=206MiB/s (216MB/s)(5120MiB/24852msec)
write: IOPS=52.7k, BW=206MiB/s (216MB/s)(5120MiB/24852msec)
¿Por qué esto solo afecta a los sistemas de archivos ZFS y no a zvols?
Pruebas extendidas para btrfs
En los comentarios, se sugirió que la diferencia puede deberse al almacenamiento en caché. Después de más pruebas, no creo que este sea el caso. Aumenté el tamaño de la prueba btrfs muy por encima de la cantidad de memoria que tiene mi computadora y su rendimiento fue significativamente mayor que el de ZFS:
/# mkfs.btrfs -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# $ fio --name rw --rw rw --size 500G --runtime 3600 --time_based --ramp_time 900
read: IOPS=41.9k, BW=164MiB/s (172MB/s)(576GiB/3600003msec)
write: IOPS=41.9k, BW=164MiB/s (172MB/s)(576GiB/3600003msec)
Información del sistema
Software
- Arch Linux, kernel versión 4.11.6
- ZFS en Linux 0.6.5.10
- fio 2.21
Hardware
- Unidad que se está probando: Seagate ST1000DM003 , conectado a un puerto SATA de 6 Gb / s
- Placa base: Gigabyte X99-SLI
- Memoria: 8 GiB
Información de ZFS
Aquí se muestran las propiedades de ZFS antes de ejecutar fio. Estos son solo el resultado de crear un zpool con la configuración predeterminada.
# zpool get all morez
NAME PROPERTY VALUE SOURCE
morez size 928G -
morez capacity 0% -
morez altroot - default
morez health ONLINE -
morez guid [removed] default
morez version - default
morez bootfs - default
morez delegation on default
morez autoreplace off default
morez cachefile - default
morez failmode wait default
morez listsnapshots off default
morez autoexpand off default
morez dedupditto 0 default
morez dedupratio 1.00x -
morez free 928G -
morez allocated 276K -
morez readonly off -
morez ashift 0 default
morez comment - default
morez expandsize - -
morez freeing 0 default
morez fragmentation 0% -
morez leaked 0 default
morez feature@async_destroy enabled local
morez feature@empty_bpobj enabled local
morez feature@lz4_compress active local
morez feature@spacemap_histogram active local
morez feature@enabled_txg active local
morez feature@hole_birth active local
morez feature@extensible_dataset enabled local
morez feature@embedded_data active local
morez feature@bookmarks enabled local
morez feature@filesystem_limits enabled local
morez feature@large_blocks enabled local
# zfs get all morez
NAME PROPERTY VALUE SOURCE
morez type filesystem -
morez creation Thu Jun 29 19:34 2017 -
morez used 240K -
morez available 899G -
morez referenced 96K -
morez compressratio 1.00x -
morez mounted yes -
morez quota none default
morez reservation none default
morez recordsize 128K default
morez mountpoint /morez default
morez sharenfs off default
morez checksum on default
morez compression off default
morez atime on default
morez devices on default
morez exec on default
morez setuid on default
morez readonly off default
morez zoned off default
morez snapdir hidden default
morez aclinherit restricted default
morez canmount on default
morez xattr on default
morez copies 1 default
morez version 5 -
morez utf8only off -
morez normalization none -
morez casesensitivity sensitive -
morez vscan off default
morez nbmand off default
morez sharesmb off default
morez refquota none default
morez refreservation none default
morez primarycache all default
morez secondarycache all default
morez usedbysnapshots 0 -
morez usedbydataset 96K -
morez usedbychildren 144K -
morez usedbyrefreservation 0 -
morez logbias latency default
morez dedup off default
morez mlslabel none default
morez sync standard default
morez refcompressratio 1.00x -
morez written 96K -
morez logicalused 72.5K -
morez logicalreferenced 40K -
morez filesystem_limit none default
morez snapshot_limit none default
morez filesystem_count none default
morez snapshot_count none default
morez snapdev hidden default
morez acltype off default
morez context none default
morez fscontext none default
morez defcontext none default
morez rootcontext none default
morez relatime off default
morez redundant_metadata all default
morez overlay off default
fuente
/etc/modprobe.d/zfs.conf
man 5 zfs-module-parameters
.Respuestas:
Mientras viejo, siento que esta pregunta merece una respuesta.
fio
emite, por defecto, IOP de tamaño 4KB; Los conjuntos de datos ZFS, en cambio, usan 128 KB de grabación por defecto. Esta falta de coincidencia significa que cada escritura 4K provoca una lectura / modificación / escritura de todo el registro de 128K.Los ZVOL, por otro lado, usan 8K volblocksize por defecto. Esto significa que una escritura 4K causa un ciclo de lectura / modificación / escritura mucho más pequeño de un registro 8K y, con algo de suerte, dos escrituras 4K pueden fusionarse en una sola escritura 8K (que no requiere lectura / modificación / escritura).
El tamaño de registro del conjunto de datos ZFS se puede cambiar
zfs set recordize=8K <dataset>
y, en este caso, debería proporcionar un rendimiento más o menos equivalente que los ZVOL. Sin embargo, cuando se usa para transferencias relativamente grandes (OP habló de archivos de 2 MB que, como imágenes, deben leerse por completo cada vez que se accede a ellos) es mejor tener un gran tamaño de registro / volblocksize, a veces incluso mayor que la configuración predeterminada (128K).fuente
Nota: como falta el trabajo de fio
direct=1
( http://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-direct ) se puede almacenar en caché una cantidad de E / S que se está realizando (tanto lectura como escritura) por el sistema operativo, distorsionando sus resultados (y haciendo que los números sean artificialmente altos). Esto en sí mismo se complica aún más por lo siguiente:O_DIRECT
(por lo que falla la apertura) o si lo hace, entonces lo hace retrocediendo silenciosamente a E / S almacenadas (consulte el punto 3 de https://github.com/zfsonlinux/zfs/commit / a584ef26053065f486d46a7335bea222cb03eeea ).O_DIRECT
a E / S almacenadas en búfer.Tenga en cuenta que
O_DIRECT
todavía se permite realizar E / S con búfer porque en LinuxO_DIRECT
es más una sugerencia (consulte la sección de referencias de /programming//a/46377629/2732969 ).Si se encuentra en una situación en la que no puede omitir correctamente los cachés, es crucial que haga suficiente E / S en un área lo suficientemente grande como para minimizar el impacto del almacenamiento en caché (a menos, por supuesto, que realmente desee probar el almacenamiento en caché) ...
fuente