Dlaczego ZFS jest o wiele wolniejszy niż ext4 i btrfs?


11

Problem

Niedawno zainstalowałem nowy dysk i utworzyłem na nim zpool:

/# zpool create morez /dev/sdb

Po dłuższym użyciu zauważyłem, że jest dość powolny:

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

Ten test jest dość podobny do mojego faktycznego przypadku użycia. Czytam umiarkowaną liczbę (~ 10k) obrazów (~ 2 MiB każdy) z dysku. Zostały napisane od razu, gdy dysk był w większości pusty, więc nie oczekuję, że zostaną podzielone.

Dla porównania przetestowałem 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)

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

Co może powodować problemy z wydajnością ZFS i jak mogę to zrobić szybciej?

Nieudana próba rozwiązania

Próbowałem również jawnie ustawić rozmiar sektora dla zpool, ponieważ mój dysk ( Seagate ST1000DM003 ) używa 4096 bajtowych sektorów fizycznych:

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

Nie poprawiło to wydajności:

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

Obserwacja

O dziwo, użycie Zvola miało świetną wydajność:

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

Dlaczego wpływa to tylko na systemy plików ZFS, a nie na Zvols?

Rozszerzone testowanie btrfs

W komentarzach zasugerowano, że różnica może wynikać z buforowania. Po dalszych testach nie sądzę, żeby tak było. Zwiększyłem rozmiar testu btrfs znacznie powyżej ilości pamięci, którą ma mój komputer, a jego wydajność była wciąż znacznie wyższa niż w przypadku 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)

Informacja o systemie

Oprogramowanie

  • Arch Linux, wersja jądra 4.11.6
  • ZFS w systemie Linux 0.6.5.10
  • fio 2.21

Sprzęt komputerowy

Informacje o ZFS

Oto jak wyglądały właściwości ZFS przed uruchomieniem fio. Są to tylko wynik utworzenia zpool z domyślnymi ustawieniami.

# 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

Brak szczegółów, takich jak używany sprzęt, system operacyjny i wersja, kontroler, ustawienia systemowe itp. Nie jestem pewien, co możemy ci powiedzieć!
ewwhite

2
Co to jest sam dysk ? To gotowy dysk SATA dla konsumentów. Przed nami jeszcze długa droga, aby udowodnić, że jest ona w stanie obsłużyć ponad 200 MB / sek. Większość dysków SATA klasy konsumenckiej w warunkach rzeczywistych będzie miała szczęście, uzyskując ponad 70-80 operacji we / wy na sekundę lub ponad 100-120 MB / s. A jeśli wykonasz losowe małe operacje blokowe we / wy na takim dysku, prawdopodobnie uzyskasz około 30-40 KB / s. 10 GB może zbyt łatwo skończyć się w pamięci podręcznej.
Andrew Henle

1
@ewwhite Brak ustawień strojenia w/etc/modprobe.d/zfs.conf
Snowball

1
@ewwhite Są. Wyczyściłem tablicę partycji między każdym testem. We wszystkich przypadkach partycja miała przesunięcie 1 MiB od początku dysku.
Snowball

1
Uwaga dla siebie / każdego, kto natknie się na to pytanie: ustawienia strojenia, o których wspomina ewwhite, są udokumentowane man 5 zfs-module-parameters.
Snowball

Odpowiedzi:


6

Choć jestem stary, uważam, że to pytanie zasługuje na odpowiedź.

fiodomyślnie wydaje IOP wielkości 4KB; Zamiast tego zestawy danych ZFS domyślnie używają opcji zapisu 128 KB. Ta niezgodność oznacza, że ​​każdy zapis 4K powoduje odczyt / modyfikację / zapis całego rekordu 128K.

ZVOL, z drugiej strony, domyślnie używają volblocksize 8K. Oznacza to, że zapis 4K powoduje znacznie mniejszy cykl odczytu / modyfikacji / zapisu rekordu 8K i przy odrobinie szczęścia dwa zapisy 4K można połączyć w jeden zapis 8K (który w ogóle nie wymaga odczytu / modyfikacji / zapisu).

zfs set recordize=8K <dataset>Rozmiar rekordu zestawu danych ZFS można zmieniać za pomocą iw tym przypadku powinien on zapewniać mniej więcej równoważną wydajność niż ZVOL. Jednak w przypadku użycia do stosunkowo dużych transferów (OP mówił o 2 MB plikach, które jako obrazy powinny być w całości odczytywane przy każdym dostępie ), lepiej jest mieć duży rozmiar nagrania / volblocksize, czasem nawet większy niż ustawienie domyślne (128 KB).


4

Uwaga: ponieważ brakuje zadania fio direct=1( http://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-direct ), pewna ilość wykonywanych operacji we / wy (zarówno do odczytu, jak i do zapisu) może być buforowana przez system operacyjny, zniekształcając wyniki (i sztucznie zwiększając liczby). Samo to dodatkowo komplikuje:

Należy pamiętać, że O_DIRECTnadal buforowanie O_DIRECToperacji we / wy jest nadal dozwolone, ponieważ w systemie Linux jest to raczej wskazówka (zobacz sekcję referencji /programming//a/46377629/2732969 ).

Jeśli znajdujesz się w sytuacji, w której nie możesz poprawnie ominąć pamięci podręcznej, bardzo ważne jest, aby zrobić wystarczająco dużo operacji we / wy na wystarczająco dużym obszarze, aby zminimalizować wpływ buforowania (chyba że rzeczywiście chcesz przetestować buforowanie) ...

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.