Warum ist ZFS so viel langsamer als ext4 und btrfs?

11

Problem

Ich habe kürzlich eine neue Festplatte installiert und einen Zpool darauf erstellt:

/# zpool create morez /dev/sdb

Nachdem ich es eine Weile benutzt hatte, bemerkte ich, dass es ziemlich langsam war:

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

Dieser Test ist meinem tatsächlichen Anwendungsfall ziemlich ähnlich. Ich lese eine moderate Anzahl (~ 10k) von Bildern (jeweils ~ 2 MiB) von der Festplatte. Sie wurden alle auf einmal geschrieben, als die Festplatte größtenteils leer war, daher erwarte ich nicht, dass sie fragmentiert sind.

Zum Vergleich habe ich ext4 getestet:

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

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

Was kann die Leistungsprobleme mit ZFS verursachen und wie kann ich es schneller machen?

Fehlgeschlagener Lösungsversuch

Ich habe auch versucht, die Sektorgröße für den zpool explizit festzulegen, da meine Festplatte ( Seagate ST1000DM003 ) physische Sektoren mit 4096 Byte verwendet:

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

Dies hat die Leistung nicht verbessert:

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

Überwachung

Seltsamerweise hatte die Verwendung eines zvol eine großartige Leistung:

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

Warum wirkt sich dies nur auf ZFS-Dateisysteme und nicht auf zvols aus?

Erweiterte Tests für btrfs

In den Kommentaren wurde vorgeschlagen, dass der Unterschied auf das Caching zurückzuführen sein könnte. Nach weiteren Tests glaube ich nicht, dass dies der Fall ist. Ich habe den btrfs-Test deutlich über den Arbeitsspeicher meines Computers hinaus erhöht und seine Leistung war immer noch deutlich höher als die von 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)

Systeminformationen

Software

  • Arch Linux, Kernel Version 4.11.6
  • ZFS unter Linux 0.6.5.10
  • fio 2.21

Hardware

ZFS-Info

So sahen die ZFS-Eigenschaften vor dem Ausführen von fio aus. Dies ist nur das Ergebnis der Erstellung eines Zpools mit den Standardeinstellungen.

# 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
Schneeball
quelle
Keine Details wie verwendete Hardware, Betriebssystem und Version, Controller, Systemeinstellungen usw. Ich bin mir nicht sicher, was wir Ihnen sagen können!
ewwhite
2
Was ist der Laufwerk selbst? Es handelt sich um ein handelsübliches SATA-Laufwerk für Endverbraucher. Sie haben noch einen langen Weg vor sich, um zu beweisen, dass es tatsächlich mehr als 200 MB / s aufrechterhalten kann. Die meisten SATA-Laufwerke für Endverbraucher unter realen Bedingungen haben das Glück, mehr als 70 bis 80 E / A-Vorgänge pro Sekunde oder mehr als 100 bis 120 MB / s zu erzielen. Und wenn Sie zufällige E / A-Vorgänge mit kleinen Blöcken an einem solchen Laufwerk ausführen, erhalten Sie wahrscheinlich 30-40 KB / s. 10 GB könnten allzu leicht im Cache landen.
Andrew Henle
1
@ewwhite Keine Tuning-Einstellungen sind vorhanden in/etc/modprobe.d/zfs.conf
Schneeball
1
@ewwhite Sie sind. Ich habe die Partitionstabelle zwischen jedem Test gelöscht. In allen Fällen hatte die Partition einen Versatz von 1 MiB vom Start der Festplatte.
Schneeball
1
Hinweis für sich selbst / alle anderen, die über diese Frage stolpern: Die Tuning-Einstellungen, die ewwhite erwähnt, sind dokumentiert man 5 zfs-module-parameters.
Schneeball

Antworten:

6

Während ich alt bin, denke ich, dass diese Frage eine Antwort verdient.

fioStandardmäßig werden IOPs mit einer Größe von 4 KB ausgegeben. ZFS-Datasets verwenden stattdessen standardmäßig 128 KB Recordize. Diese Nichtübereinstimmung bedeutet, dass jeder 4K-Schreibvorgang ein Lesen / Ändern / Schreiben des gesamten 128K-Datensatzes verursacht.

ZVOLs verwenden dagegen standardmäßig 8K Volblocksize. Dies bedeutet, dass ein 4K-Schreibvorgang einen viel kleineren Lese- / Änderungs- / Schreibzyklus eines 8K-Datensatzes verursacht und mit etwas Glück zwei 4K-Schreibvorgänge zu einem einzigen 8K-Schreibvorgang zusammengeführt werden können (für den überhaupt kein Lesen / Ändern / Schreiben erforderlich ist ).

Die Datensatzgröße von ZFS-Datasets kann mit geändert werden zfs set recordize=8K <dataset>. In diesem Fall sollte die Leistung mehr oder weniger gleichwertig sein als bei ZVOLs. Bei Verwendung für relativ große Übertragungen (OP sprach von 2-MB-Dateien, die als Bilder bei jedem Zugriff vollständig gelesen werden sollten) ist es jedoch besser, große Dateien zu haben Aufzeichnungs- / Volblockgröße zu haben, die manchmal sogar größer ist als die Standardeinstellung (128 KB).

Shodanshok
quelle
4

Hinweis: Da der fio-Job fehlt direct=1( http://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-direct) Da ), kann ein Teil der ausgeführten E / A (sowohl Lesen als auch Schreiben) zwischengespeichert werden durch das Betriebssystem, verzerren Sie Ihre Ergebnisse (und machen Sie die Zahlen künstlich hoch). Dies selbst wird durch Folgendes weiter erschwert:

Beachten Sie, dass O_DIRECTgepufferte E / A weiterhin zulässig sind, da unter LinuxO_DIRECT eher ein Hinweis ist (siehe den Referenzabschnitt unter /programming//a/46377629/2732969 ).

Wenn Sie sich in einer Situation befinden, in der Sie Caches nicht korrekt umgehen können, ist es wichtig, dass Sie genügend E / A über einen ausreichend großen Bereich ausführen, um die Auswirkungen des Cachings zu minimieren (es sei denn, Sie möchten das Caching tatsächlich testen) ...

Anon
quelle