Perché ZFS è molto più lento di ext4 e btrfs?


11

Problema

Di recente ho installato un nuovo disco e creato uno zpool su di esso:

/# zpool create morez /dev/sdb

Dopo averlo usato per un po ', ho notato che era piuttosto 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)

Questo test è abbastanza simile al mio caso d'uso reale. Sto leggendo un numero moderato (~ 10k) di immagini (~ 2 MiB ciascuna) dal disco. Sono stati scritti tutti in una volta quando il disco era quasi vuoto, quindi non mi aspetto che siano frammentati.

Per confronto, ho provato 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)

E 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)

Cosa potrebbe causare i problemi di prestazioni con ZFS e come posso renderlo più veloce?

Tentativo fallito di soluzione

Ho anche provato a impostare esplicitamente la dimensione del settore per zpool, poiché il mio disco ( Seagate ST1000DM003 ) utilizza settori fisici da 4096 byte:

/# zpool create -o ashift=12 morez /dev/sdb

Ciò non ha migliorato le prestazioni:

/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)

Osservazione

Stranamente, usare uno zvol ha avuto grandi prestazioni:

/# 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)

Perché questo ha effetto solo sui filesystem ZFS e non su zvols?

Test estesi per btrfs

Nei commenti, è stato suggerito che la differenza potrebbe essere dovuta alla memorizzazione nella cache. Dopo ulteriori test, non credo che sia così. Ho aumentato le dimensioni del test btrfs ben al di sopra della quantità di memoria del mio computer e le sue prestazioni erano ancora significativamente superiori a quelle di 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)

Informazioni di sistema

Software

  • Arch Linux, versione del kernel 4.11.6
  • ZFS su Linux 0.6.5.10
  • fio 2.21

Hardware

Informazioni ZFS

Ecco come apparivano le proprietà ZFS prima di eseguire fio. Questi sono solo il risultato della creazione di uno zpool con le impostazioni predefinite.

# 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

Nessun dettaglio come l'hardware in uso, il sistema operativo e la versione, il controller, le impostazioni di sistema, ecc. Non sono sicuro di cosa possiamo dirti!
ewwhite,

2
Qual è l' unità stessa? È un'unità SATA consumer standard. Hai ancora molta strada da fare per dimostrare che può effettivamente gestire oltre 200 MB / sec sostenuti. La maggior parte delle unità SATA di livello consumer in condizioni reali sarà fortunata a ottenere oltre 70-80 operazioni di I / O al secondo, o più di circa 100-120 MB / sec. E se si eseguono operazioni I / O a blocchi piccoli casuali su tale unità, è probabile che si ottenga qualcosa come 30-40 KB / sec. 10 GB potrebbero essere finiti troppo facilmente nella cache.
Andrew Henle,

1
@ewwhite Non sono presenti impostazioni di ottimizzazione in/etc/modprobe.d/zfs.conf
Snowball,

1
@ewwhite Lo sono. Ho cancellato la tabella delle partizioni tra ogni test. In tutti i casi, la partizione aveva un offset di 1 MiB dall'inizio del disco.
Snowball,

1
Nota per sé / chiunque altro inciampa su questa domanda: le impostazioni di ottimizzazione menzionate da ewwhite sono documentate man 5 zfs-module-parameters.
Snowball,

Risposte:


6

Quando sono vecchio, sento che questa domanda merita una risposta.

fioemette, per impostazione predefinita, IOP di dimensioni 4KB; I set di dati ZFS, invece, utilizzano 128 KB per impostazione predefinita. Questa mancata corrispondenza indica che ogni scrittura 4K provoca una lettura / modifica / scrittura dell'intero record da 128 KB.

Le ZVOL, d'altra parte, usano 8k volblocksize di default. Ciò significa che una scrittura 4K causa un ciclo di lettura / modifica / scrittura molto più piccolo di un record 8K e, con un po 'di fortuna, due scritture 4K possono essere riunite in una singola scrittura 8K (che non richiede alcuna lettura / modifica / scrittura).

Il set di dati del set di dati ZFS può essere modificato con zfs set recordize=8K <dataset>e, in questo caso, dovrebbe fornire prestazioni equivalenti più o meno equivalenti agli ZVOL. Tuttavia, se utilizzato per trasferimenti relativamente grandi (OP parlava di file da 2 MB che, essendo immagini, dovrebbero essere letti interamente ogni volta che si accede) è meglio avere dimensioni record / volblock di grandi dimensioni, a volte anche più grandi dell'impostazione predefinita (128K).


4

Nota: poiché manca il lavoro fio direct=1( http://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-direct ) è possibile memorizzare nella cache una parte dell'I / O in esecuzione (sia in lettura che in scrittura) dal sistema operativo, distorcendo i risultati (e rendendo i numeri artificialmente alti). Questo stesso è ulteriormente complicato dal seguente:

Tenere presente O_DIRECTche è ancora consentito eseguire operazioni di I / O con buffer perché su Linux O_DIRECTè più un suggerimento (consultare la sezione riferimenti di /programming//a/46377629/2732969 ).

Se ti trovi in ​​una situazione in cui non puoi bypassare correttamente le cache, è fondamentale che tu faccia un I / O sufficiente su un'area abbastanza grande da ridurre al minimo l'impatto della cache (a meno che, ovviamente, non desideri effettivamente testare la cache) ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.