ZFS Performance Q

В незапамятные времена, а именно четыре года назад, я намерял, что от ускорения процессора (или памяти?) ZFS-у бывает счастье. Было это на FreeBSD 9-STABLE.

Прошло четыре года и вопрос опять нагревается, хочу поменять 65-ваттные процессоры в ящиках на что-то попроще, а заодно добавить шпинделей и L2ARC.

FreeBSD у меня в одном ящике 10-STABLE, а в другом 11-чего-то там.

Ну и вопрос, собственно, более конкретный:

Что ему (ZFS на актуальных FreeBSD) более любо: частота, количество ядер или вовсе DDR4 RAM?

Или может там вообще все оптимизировали по самые гланды и сойдет и Atom? Или не Atom, а 20-вт Pentium D?

Скорости которые меня интересуют - мегабайт 700-900 в секунду (три старых SSD-шки в L2ARC, ~10 шпинделей в RAIDZ2).

Comments

Понятно, что таргет у тебя ультрабольшие изображения, но всё рано, прикинь, сколько ты IOPS хочешь снять (и, кстати, возможно, из этого будет следовать что L2ARC потребуется ограничить metadata)

Ну вопрос конкретный: о влиянии CPU/памяти на ZFS. Оно было подмечено 4 года назад, но может что изменилось?

Как и что разбрасывать по томам, чтобы бэкапы не выедали L2ARC - это другой вопрос, хотя тоже важный (по всей видимости, придется делать "рабочий" zpool и "архивный" и L2ARC на SSD - только рабочему)

по моим наблюдениям, запаса CPU у нас обычно есть даже везде включить lz4. А вот памяти много не бывает, и latency там, кажется, играют большую роль чем потоковая скорость.

Но -- надо ставить эксперименты.

Ну типичная нагрузка на файлер - она вряд-ли сотни мегабайт потока в единичных потоках?
А скорее много потоков - и за счет драки за seek существенно ниже реальная полоса чтения.

В этой ситуации, понятно, упора в CPU (ну там в подсчет чексум) не будет или будет меньше.

Я бы такое спрашивал в списках рассылки даже не Фряхи (хотя можно в fs@), а OpenZFS.

Ну это верное замечание, но
а) а может кто уже что-то такое мерял? Ну вот я же мерял 4 года назад

б) припираться в (новую для себя) рассылку/форум, задавать там вопрос (который, возможно, миллион раз обсуждали уже) - это большой шанс выставить себя идиотом. Ничего страшного в этом нет, ну идиот, бывает, проблема в том, что идиотам по существу не отвечают

Ну вот в fs@ особо не обсуждали. И тебе именно нужны те, кто померял, я думаю, там их будет куда больше, чем среди твоих читателей. Ну, то есть, вероятность будет больше :)

Ну вот в fs@ меня начали учить жизни, что зеркала быстрее. Ну ох@еть теперь.

Я думал, это синдром русскоязычных коммьюнити…

Самое смешное, что для моей задачи - очень маленькое количество потоков чтения записи - это кажется не так и raidz должен быть быстрее.

raidz по записи будет медленее, чем такой же по объёму страйп из дисков/зеркал. Это вытекает из транзакционности записи в zfs и большому пенальти raidz при read-modify-write. Простым языком - количество записываемой информации на диски будет больше при raidz. Это достаточно легко проверить записав файл и проверив сколько реально было записано на все диски информации (понятно, что при заполнении пула этот эффект будет проявляться всё больше и больше). Для повышения скорости записи больших файлов можно отключить zil (на отказоустойчивость не влияет), изменить logbias, redundant_metadata, что также влечёт уменьшение количества записываемой информации. Добившись минимальных накладных расходов при записи оцениваем загрузку дисков gstat-ом. Если имеем 100% загрузку дисков при записи файла - система упирается в скорость дисков, если нет ищем во что упираемся.

Ну подождите, при N-way mirror - запись увеличивается в N раз. При N-disk/K-raid - в N/(N-K)

Ну и на глазок - похоже.

В зеркале два или более диска пишут одинаковую информацию параллельно, поэтому можно считать, что зеркало пишет со скоростью одного диска (правильнее со скоростью самого медленного). Можно для тестов вообще не делать зеркала. Я сравнивал пул одинакового размера.

Не, ну вопросов нет, страйп быстрее raidz из того же количества дисков.

Но вот когда вы хотите обеспечить устойчивость к выпадению (двух любых) дисков (к примеру) - уже не все так однозначно....

Проигрыш в объеме при использовании зеркал однозначен, зато выигрыш в скорости записи и при чтениии более, чем в один поток.

raidz потерю двух не переживёт. raidz2 ещё больше тормоза. Но я так понял речь шла не о отказоустойчивости.

В наше сложное время без оказоустойчивости очень плохо. Статистика по дискам доступна, 25% вылетов в первый год - встречается.

Ну где "выигрыш в скорости записи то"?

Я еще раз повторяю, в N-way mirror мы пишем в N раз больше данных. В raidN на K дисках: в K/(K-N) раз.

Вывод: при фиксированном N (скажем, два) и фиксированном K (большем чем 2N) - raid будет быстрее на запись (но медленнее на чтение)

Наверно я плохо понимаю, поэтому простой пример - пусть один zpool из двух mirror по два диска (всего 4 диска в пуле) и пул raidz такой же емкости из трёх дисков (как вариант можно рассмотреть ещё raidz2 из 4 дисков). Если сравнивать скорости чтения/записи (понятно нужно оговаривать характер нагрузки), то быстрее будет первый пул.
Я работаю с полиграфическими данными (небольшая компания), поэтому мне очень близка данная тема (Photoshop, Illustrator, InDesign, Acrobat, большие файлы, скорость передачи по сети).

Нет, давайте мы будем рассматривать одинаковое количество дисков, иначе ерунда получается совсем.
И не будем рассматривать "raidz2 из 4-х", это конечно более надежная штука, чем striped mirror 2x2, но и все.

Ну и количество дисков возьмем какое-то вменяемое, ну там 10.

А еще лучше - 12, потому что делится на все.

Получается 5 зеркал по 2 диска (полезная емкость 5*N) и raidz из 10 дисков (полезная емкость 9*N). Максимальная физическая скорость записи первого пула приблизительно 5*V, максимальная скорость второго пула приблизительно 9*V. Но zfs это не голые диски, поэтому для сравнения необходимо определить какой размер recordsize у zfs и размер страйпа у raidz (под страйпом понимается размер блока на одном диске, который входит в общий страйп при записи на все диски)? Также какое количество копий метаданных при записи определено для пула (для данных считаем одну копию)? Оценка скорости будет не совсем однозначная как кажется на первый взгляд.

Всегда же можно достать и померять. Вот копируем с винды на ZFS папку с большой виртуальной машиной (с единичной SSD, т.е. эти 450MB/s - это может быть вообще скорость источника):

Вот что говорит zpool iostat -v 10 (10 - чтобы как-то усреднил) примерно в момент скриншота:

                                           capacity     operations    bandwidth
pool                                    alloc   free   read  write   read  write
--------------------------------------  -----  -----  -----  -----  -----  -----
zdata                                   11,7T  10,0T      4    616  50,0K   451M
  raidz1                                11,7T  10,0T      4    616  50,0K   451M
    gptid/6d3f4070-3cdb-11e4-bb7d-001b21712630      -      -      0    509  9,20K  91,4M
    gptid/d6a2b2b5-3057-11e4-b611-001b21712630      -      -      0    505  5,20K  91,4M
    gptid/1e257ad1-2213-11e4-9cc0-001b21712630      -      -      0    502  8,00K  90,8M
    gptid/31eec4e7-a2d4-11e3-a262-001b21712630      -      -      1    503  10,8K  91,8M
    gptid/3321938d-a2d4-11e3-a262-001b21712630      -      -      0    505  4,80K  91,0M
    gptid/a189697b-1714-11e4-90ed-001b21712630      -      -      1    500  12,0K  90,6M
--------------------------------------  -----  -----  -----  -----  -----  -----

 

Что мы видим:

1) На пул пишется 451 данных, а винда показывает 446. Это либо точность измерения, либо тот оверхед, о котором вы говорите. Она (точность)/он(оверхед) в районе 1-2%

2) На диски пишется 6*91 = 546Mb/s данных + четности

3) Сколько мы ожидаем "данных плюс четности"?  451*6/5 = 541. Опять, то ли в пределах точности (я все цифры у дисков округлил до 91, на глазок, может и зря) то ли еще 1% оверхеда.

Ну вот 9*V минус несколько процентов оверхеда - будут сильно быстрее 5*V.

 

Пардон за форматирование. Если нажать в комменте выше reply - Вы его увидите в полную ширину.

Очень хорошо, что под рукой есть raidz на 6 дисков. Если можно перед копированием дать iostat -Ix. Скопировать большой файл и опять дать iostat -Ix. Сравнить размер файла с тем, сколько реально записалось на диски. Если пул был пустой, то можно получить минимальный возможный оверхед при записи. Если на пуле были данные, была фрагментация, то более менее реальный.

Если измерять чистую скорость пула, то можно ограничиться dd if=/dev/zero of=файл на пуле, тогда можно считать максимально возможный источник по скорости. Также можно dd просто прочитать какой то объём с одного диска и узнать приблизительную скорость одного диска (запись и чтение почти одинаковы).

Если на пуле не было данных, то для чистоты эксперимента можно пересобрать пул на трёх зеркалах и подтвердить соотношение 3*V против 5*V :).

На пуле - есть данные, примерно 12Tb, спрятать некуда

У меня наверно найдётся максимум четыре пустых диска, но это похоже не интересно :). Всё таки интересно получить iostat -Ix до и после записи большого файла, тем более пул с данными.

Я ж написал. По одному диску, но там по всем 6-ти за три дня аптайма цифры близкие.

Я не могу остановить жизнь по всему дому и поставить чистый эксперимент. С другой стороны, "по всему дому" за время эксперимента - вряд-ли больше пары гигов записали, поэтому почти чистый получился.

На 1-м диске (по всем - не стал):
before = 101321660 kw/i
Пишем набор файлов (крупных) 56603105725 байт.
На каждый диск из шести должно лечь 9212745 килобайт "чистых данных" (предыдущее число делить на 6) (считая что в килобайте - 1024, не знаю как iostat считает)
after = 112879668
То есть легло: 11558008

Оверхед получается 1.254. Ожидаемый - 1.2 (6/5). Ну вот опять - единицы процентов оверхеда, с точностью то time machine на мак мини жены (ну не стал я проверять, работает оно там у нее или нет)

По дефолтным настройкам zfs имеет оверхед по записи приблизительно +30% от записываемого объёма (вне зависимости от организации vdev). Если поиграться можно снизить до 4-5% (у меня больше не получалось, правда не использовал больших recodsize). Тоже немного поэксперементировал с raidz. Скорость оценить не могу, так как использовал разделы одного диска. Но по объёму записываемой информации получил похожие результаты. Пенальти не вылазит, даже при случайной модификации большого файла :). Возможно, если объём записанных данных будет сравним или превосходить размер пула (имеется ввиду с учётом модификаций и удалений), то начнёт что-то вылазить.

Ну проверить то - недолго.

Беру виртуальную машину:

$uname -a
FreeBSD homefbsd 10.2-STABLE FreeBSD 10.2-STABLE #7 r286827: Sun Aug 16 22:11:36 MSK 2015

Подцепляю к ней в виртуальный же диск на 8 гигабайт, прямо на ходу

da1: <VMware, VMware Virtual S 1.0> Fixed Direct Access SCSI-2 device
da1: 320.000MB/s transfers (160.000MHz DT, offset 127, 16bit)
da1: Command Queueing enabled
da1: 8192MB (16777216 512 byte sectors: 255H 63S/T 1044C)

Создаю zpool и смотрю что получилось

zpool create ztest /dev/da1
zpool list -v
NAME                                     SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
ztest                                   7,94G    89K  7,94G         -     0%     0%  1.00x  ONLINE  -
  da1                                   7,94G    89K  7,94G         -     0%     0%

Cоздаю файловую систему, не в пул же писать

zfs create ztest/ztest1

Пишу туда файл на весь размер:

dd if=/dev/zero of=/ztest/ztest1/file bs=1024M
8+0 records in
7+1 records out
8255045632 bytes transferred in 238598.581299 secs (34598 bytes/sec)

Смотрю что вышло:

ls -l /ztest/ztest1/file
-rw-r--r--  1 root  wheel  8255045632 May 22 13:28 file

Значит влезло 8255045632 байт, а места было 16777216*512 = 8589934592 байт

Делим, получаем 0.96101, то есть 4% оверхед.

Как вы получили 30% - не понимаю!

 

Другой вопрос, что еще 10% рекомендуют держать пустыми т.к. там есть песня про фрагментацию.

Проверил свои тесты, благо я записал статистику в файл. Всё верно плюс/минус 1%. Я в начале считал всё тоже только по первому диску, перепроверил для всех дисков входящих в raidz.

Для теста были созданы 6 разделов по 512GB. Из этих разделов создал raidz из 6 дисков. Создал файловую систему по умолчанию. С помощью dd записал файл в 64GB блоками по 128k. На все диски записалось 98,6GB. Если учесть, что должно было записаться в 1,2 раза больше (76,8GB), то получился оверхед 28%. Затем с помощью fio в этот файл записал случайным образом 256MB блоками по 128k. Записалось 402,9MB. С учётом коэффициента 1,2 получилось 31% оверхеда. Получачается при при модификации файла в таких условиях пенальти отсутствует (чтения не наблюдалось вообще). Также заметил, что после снятия статистики данные ещё некоторое врямя писались на диск из кеша. Поэтому результаты могут незначительно отличаться в большую сторону. Вспомнил, что когда-то раньше разбирался с низкой производительностью zvol на 3TB и тогда выяснил, что пишется где-то на 30% больше. Правда там recordsize по умолчанию по-моему был 8k. Поэтому сделал вывод, что на созданных по умолчанию файловых системах оверхед при записи приблизительно 30%.

Повторил Ваш тест. Правда размер диска был 32GB. Всё подтвердилось - размер файла был 96%, от размера диска, а оверхед по записи 1,8%! Задумался. Подумал маленький размер диска по сравнению с объёмом памяти (на машине 16GB).
Создал раздел на 3TB (как и в случае теста с raidz 6*512GB), сформировал zfs по умолчанию и стал писать dd файлы по 64GB. Получил такие цифры оверхеда: первый файл - 8,4%, 2 - 13,9%, 3 - 14,6%, 4 - 10,6%, 5 - 12,7%, 6 - 11%. Получается оверхед по записи зависит от множества факторов :).

C маленьким recordsize на raidzN с неподходящим количеством дисков - действительно будет большой оверхед (и как я понимаю, если взять ashift=12 и recordsize=4k, то из raidz2 мы эффективно получим 3-way mirror).

Но размер записи стандартный - 128к а не 8. В том числе и по этой причине.

Во всех описываетых ранее тестах размер recordsize был 128k.

Дошли руки провести простенький тест из 4 дисков (WD Black 2T). Создавался raidz из 4 дисков и страйп из двух зеркал. Все настройки для файловых систем были одинаковы (немного оптимизированны, кеширование только для метаданных). Что бы не усложнять и обеспечить простую воспроизводимость, тест делался с помощью dd. Вначале записывался файл 64GB, затем 256GB, затем ещё один на 64GB. Соотношение скоростей записи 1,42, 1,4, 1,44. Очень близко к теоретическому 1,5 :). Затем последовательно читался первый и второй файл. Соотношение скоростей чтения 1,42, 1,37, что тоже довольно близко к 1,5. Последний тест - чтение первого и третьего файла одновременно. Соотношение суммарной скорости чтения 0,74, то есть страйп из двух зеркал быстрее raidz в 1,34 раза. Зная, что алгоритм балансировки чтения у встроенного в zfs зеркала, мягко говоря, оставляет желать лучшего. Повторил тест на страйпе из зеркал с лучшим алгоритмом балансировки. По записи тоже самое, по чтению 1,2, 1,2, 0,38. Получается при чтении в два потока raidz медленнее zfs на двух зеркалах в 2,6 раза. Для понимания порядка цифр - raidz в один поток чтения выдавал 343MB/s, в два потока суммарно 186MB/s. zfs на двух зеркалах - в один поток 285MB/s, в два потока суммарно 484 MB/s.

Ну да, два потока можно сбалансировать по двум зеркалам - и здорово, что такая оптимизация есть.

При увеличении потоков чтения - разница будет возрастать.

Я не думаю что "возрастать".
Вот давайте представим что у нас 4 набора данных, расположенных в начале, 1/3, 2/3 и конце массива.
В raidz - ну там будет full-stroke seek всю дорогу и "хуже уже не станет" (относительно случая "читаем 1-й и 4-й наборы", хуже уже некуда).

Зеркало и два потока: каждый поток спозиционируется на своей области дисков, seek-ов лишних почти нет, счастье.
Зеркало и 4 потока: будем удовлетворять запросы с 1-й половины диска - с одной половинки зеркала, со второй - со второй половинки зеркала.
При росте числа потоков - у нас будут и там и сям половинные seeks, да это вне всякого сомнения быстрее, чем full-stroke.

Но оптимизация определяется именно количеством копий. Будет 10 копий (и много потоков) - ну на 10 зон побъем диски.

С рассуждениями почти полностью согласен. Но в данном примере на 4 потока в raidz каждая головка диска обязательно будет летать в четыре разные позиции (в какой последовательности неясно, но минимум на 1/4 часть диска, предположим в среднем 1/2, если в среднем сильно больше, тогда совсем беда). В случае зеркал в лучшем случае одна головка будет делать перемещение только на 1/4, что впрочем тоже ещё нужно доказать. Получается на вскидку имеем двукратное превосходство. Хотя чутьё мне подсказывает :) (https://github.com/geomflash/geomflash/blob/master/Performance%20raid1%2...), что будет "разница будет возрастать".
"Всегда же можно достать и померять ©". Можем проверить пока тестовая машина доступна. При страйпе зеркал доступно 3,62TB. Предлагаю последовательно писать файлы 8GB - 1GB - 8GB - 1GB - 8GB - 1GB - 8GB. Затем читать только 8GB файлы. Читаем первый файл, читаем одновременно первый и последний, читаем одновременно первый, второй и последний. Читаем одновременно все файлы. У raidz в этом тесте будет преимущество, так как для него это будет заполнение 2/3 объёма и максимальное перемещение головки диска будет меньше. Тем интереснее, какой будет результат :). Тест будет довольно длинный по времени, поэтому если есть предложения/замечания готов учесть.

Я ошибся не 1GB, а 1TB. Получается 8GB - 1TB - 8GB - 1TB - 8GB - 1TB - 8GB.

Да-да, в зеркале будут не full-stroke, а половинки. В 3-way-зеркале - трети, вопросов нет.

Вопрос в том, какой реальный паттерн реальной нагрузки. Вот к примеру на сервере где blog.lexa.ru - чтений 1% (потому что памяти больше чем надо - и все вообще что читалось - лежит в кэше).
В файлере моем домашнем - 43% чтений и 57% записи....

Проверялось соответствие формулы 2V против 3V. Из кеша проверять нету смысла :). Можно задать с помощью fio любую нагрузку, но вопрос какую? И как потом оценить?

Вот меня (с моим паттерном - важен один поток) порадовало кстати то, что raidz в один поток читает быстрее.

Довольно неожиданный результат, я ожидал что zfs зеркало умеет правильно нагрузить и для одного потока.

(может быть префетч выключен и включение - изменит это?)

Для любого зеркала (двойное, тройное, ...) одно последовательное чтение не может принципиально быть быстрее скорости чтения с одиночного диска (точнее самого быстрого диска в зеркале). В gmirror-е есть алгоритм балансировки (по-моему split), который пытался это делать. Можно оценить результат :). Только в варианте фрагментации файла и необходимости читать метаданные, расположенные в другом месте, возникает профит, что кстати в основном и бывает.
В тесте было выключено кеширование данных и префетч, иначе как тогда можно было бы интерпретировать результаты. Но префетч скорость чтения для одного последовательного чтения у одного зеркала не повысит. Моё мнение префетч это только для твоей нагрузки :).

Блин, пора завязывать: менять "тему оформления" я не готов, а читать невозможно уже.

Казалось бы: читаем четные гигабайты (дорожки, конечно) с одной половинки зеркала, нечетные - с другой. Вот и экономия. Но, понятно, должен быть префетч и на изрядную глубину.

:).

Был не прав в своём предыдущем утверждении. Сегодня обнаружил, что при включённом кешировании данных и префетче. Алгоритм балансировки зеркала в zfs может, условно говоря, работать по предложенному тобой алгоритму :-). Мало того для чтения в один поток можно разгонять (подстраивать под конкретные диски) скорость чтения, меняя sysctl. Сегодня увидел результат с той же пары зеркал в 440MB/s при чтении одного файла. Впечатлило. Век живи век учись :-).

Я на всякий случай спрошу: ты же понимаешь, что у RAIDZx должно быть 2^n + x дисков или ZFS радостно будет терять место, да?

Нет, не понимаю!

Вот delphix:

A misunderstanding of this overhead, has caused some people to recommend using “(2^n)+p” disks, where p is the number of parity “disks” (i.e. 2 for RAIDZ-2), and n is an integer. These people would claim that for example, a 9-wide (2^3+1) RAIDZ1 is better than 8-wide or 10-wide. This is not generally true

То есть на больших record size это должно эффективно прятаться.

Но не до конца. Я сейчас не дома, а в понедельник поищу гуглдоковскую табличку калькулятор где вино когда сколько теряется.
Рекордсайз же должен резаться на диски с данными.

Я кажется видел этот калькулятор им. delphix.
Он для базоданновых recordsize, 8-16 килобайт.
Но стандартный размер - 128k (и там уже все лучше), а я ставлю у себя вовсе 1M

То есть потери есть, с этим я не спорю, просто при recordsize в 256 секторов (1M по 4k сектор) округления до 3-4 (они там до 1+p, где p - избыточность) не будут заметны.

Т.е. рекордсайз делится на число дисков (минус чётность), и получившееся округляется вверх до делимости на минимальный рекордсайз, (т.е. эффективно 4K в нынешних условиях).
На мелких файлах как ни крути терять будешь, а на больших при неудачном числе дисков.

Ох йо, как жэ ж оно косо форматирует при большой глубине вложенности-то!

И подветку отдельно не поглядеть, в отличие от LJ :(

Лёх, с этим ничего нельзя сделать?

Такие длинные треды бывают редко - и я ленюсь (ну и сам читаю через RSS).

Когда-нибудь - починю. Но ведь лень!

Я подумал - нет, не буду чинить.
Потому что если починить, то заведутся бесконечные темы с бесконечными комментариями. А сейчас они сами затухают - и это прекрасно

Злой ты ;)

Впрочем, я тебя понимаю, да.