Назад | Перейти на главную страницу

Почему `zfs list -t snapshot` на порядки медленнее, чем` ls .zfs / snapshot`?

Со всеми версиями ZFS-on-Linux, которые я когда-либо пробовал, используя zfs list чтобы перечислить все снимки файловой системы или тома (zfs list -r -t snapshot -H -o name pool/filesystem) всегда требует на выполнение на много порядков больше времени, чем ls .zfs/snapshot, что немедленно:

$ time ls -1 /srv/vz/subvol-300-disk-1/.zfs/snapshot
[list of 1797 snapshots here]
real    0m0.023s
user    0m0.008s
sys     0m0.014s

# time zfs list -r -t snapshot -H -o name vz/subvol-300-disk-1
[same list of 1797 snapshots]
real    1m23.092s
user    0m0.110s
sys     0m0.758s

Эта ошибка характерна для ZFS-on-Linux?

Может ли кто-нибудь с системой ZFS Solaris или FreeBSD выполнить аналогичный тест (на файловой системе с сотнями снимков состояния на вращающихся жестких дисках)?

Есть ли обходной путь, чтобы получить быстрый список снимков для объем, который по своей природе не имеет .zfs каталог?

Я провел вышеуказанный тест с ZFS-on-Linux 0.6.5.2-2-wheezy на ядре 2.6.32-43-pve x86_64 (Proxmox), но я всегда видел эту проблему, как на старых, так и на новых ZFS и ядре. версии.


Вот статистика пула:

# zpool list
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
vz    25.2T  9.42T  15.8T         -     5%    37%  1.00x  ONLINE  -

Он содержит 114 файловых систем и 1 том, каждый с сотнями снимков, так как это zfs send / zfs recv резервный сервер.


Решение: zfs list работает медленно, потому что получает дополнительную информацию, даже если она не отображается. Решение заключается в добавлении обоих -o name -s name, то есть используя zfs list -t snapshot -o name -s name

zfs list -t snapshot на выполнение всегда уходит на много порядков больше времени, чем ls .zfs/snapshot

Вы также сравниваете две совершенно разные операции.

zfs list -t snapshot перечисляет все снимки ZFS в системе - и предоставляет много информации об этих снимках, например об объеме используемого пространства. Запустите это под strace чтобы увидеть сделанные системные вызовы.

ls .zfs/snapshot просто генерирует простой список имен из каталога. Нечего делать, кроме как читать имена - и ничего больше не сообщать.

Операции со снимками зависят от количества имеющихся снимков, оперативной памяти, производительности диска и места на диске. Это общая проблема ZFS, а не что-то уникальное для варианта Linux.

Лучший вопрос: Почему у вас 1797 снимков звола? Это определенно больше, чем рекомендуется, и заставляет меня задуматься, что еще происходит в системе.

Люди говорят: «Снимки ZFS бесплатны», но это не всегда так.

Хотя привязки ZFS не влияют на производство производительность, большое число, которое у вас есть, явно требует доступа к диску для перечисления.

Disk access time > RAM access time, отсюда и порядок величины разницы.


strace вывод. Обратите внимание на время, затрачиваемое на один системный вызов, и представьте, насколько плохо он будет масштабироваться с количеством снимков в вашей файловой системе.

# strace -c ls /ppro/.zfs/snapshot

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0        10           read
  0.00    0.000000           0        17           write
  0.00    0.000000           0        12           open
  0.00    0.000000           0        14           close
  0.00    0.000000           0         1           stat
  0.00    0.000000           0        12           fstat
  0.00    0.000000           0        28           mmap
  0.00    0.000000           0        16           mprotect
  0.00    0.000000           0         3           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         2           ioctl
  0.00    0.000000           0         1         1 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           fcntl
  0.00    0.000000           0         2           getdents
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0         1           statfs
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         2         1 futex
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         1           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                   133         2 total

против

# strace -c zfs list -t snapshot

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.003637          60        61         7 ioctl
  0.00    0.000000           0        12           read
  0.00    0.000000           0        50           write
  0.00    0.000000           0        19           open
  0.00    0.000000           0        19           close
  0.00    0.000000           0        15           fstat
  0.00    0.000000           0        37           mmap
  0.00    0.000000           0        19           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         4           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         3         1 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         2         1 futex
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         1           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    0.003637                   250         9 total