В последний раз о фрагментации файлов и производительности
Я много раз в этом блоге трогал тему о влиянии фрагментации на производительность работы системы хранения (см. например раз, два, три). Но как-то все это были слова, а как насчет “покажь логи”? Так как я до недавних пор был “безлошадный”, а все мои знакомые “с оборудованием” все как на подбор были “ленивы и нелюбопытны”, чтобы дать документальный ответ на этот вопрос, то поэтому пришлось отвечать самому.
Тут вот, как вы уже заметили, я, наконец, обзавелся на хозяйстве маленьким нетаппчиком, и, пока мы его в продакшн не ввели, гоняю в хвост и в гриву, в том числе отвечаю на назревшие вопросы. ?? первый – о том, влияет ли фрагментация данных на производительность доступа к ним при рандомном характере доступа.
Выше в постах, на которые я сослался, я уже ответил на этот вопрос и прояснил свою позицию. Вкратце: при рандомном доступе производительность от фрагментации данных не зависит. Так как система хранения обращается к данным рандомно, в произвольном, случайном порядке, то нет никакой особенной разницы в том, будут ли блоки данных лежать упорядоченно, или беспорядочно – их всегда будут читать “беспорядочно”. А рандомность обращения, помноженная на рандомность размещения не дает “рандомность в квадрате”, она остается обычной рандомностью, “в первой степени”.
Надеюсь не нужно дополнительно объяснять, почему для современных многозадачных систем, для баз OLTP, для виртуализованных серверных сред почти 100% доступа к данным является рандомным? Последовательный, “секвентальный” доступ встречается в очень узком сегменте, это бэкапы (а у NetApp, к слову, задача бэкапа, как вы помните, решается другим способом, а не последовательным копированием и передачей данных), это базы с характером доступа DSS, и это, отчасти, логи баз данных. Вот, в общем, и все использование секвентального доступа. Остальное все – более или менее чистый рандом.
Поэтому я взял паттерн доступа VM-сервер (40%-write/60%-read, 45%-sequental/55%-random, 4KB block). Секвентальность в последнем случае берется вследствие работы локального кэша хоста. Паттерны эти определил не я, они довольно широко распространены. Вот его и будем кушать мерять.
Тестировал я с помощью IOmeter, который, несмотря на некоторые его недостатки, знаю и люблю. В качестве load-generator использовались виртуальные машины, работающие с достаточно мощного хоста (IBM 3850 X5), который был подключен к стораджу по NFS. Для OS в VM диск выглядел “физическим” LUN без файловой системы, который делался MBR-разделом и форматировался в NTFS со стандартным размером блока (4KB). Раздел делался размером 40GB, на нем создавался тестовый файл IOmeter (iobw.tst), размером 16GB (для гарантированного “пробоя кэша”). На каждой VM делался 4-процессорный vCPU, и, соответственно, запускались 4 Worker, на каждом из которых пускался тестовый паттерн на созданный диск, в 16 потоков ввода-вывода (Outstanding IOs) на каждый Worker, то есть 64 одновременных потока ввода-вывода на диски (контроллер NetApp). Загрузка хост-сервера тестом не превышала при этом 15% (мощная зверюга этот 3850), загрузка стораджа колебалась, но также не превышала 80%. То есть заведомо мы в “потолки” нигде не упирались.
Для минимизации эффектов “прогрева WAFL” (о котором еще будет пост, это также была одна из тем “исследовательской недели”) я делал длинный ramp-up (10 минут), а затем начинался собственно измеряемый тест, длиной 30 минут. Я брал для оценки значение в steady state, ближе к концу теста, и для оценки параллельно проверяемого эффекта “падения производительности” при прогреве – ближе к его началу.
Однако, перед исследователем, в моем лице, встала проблема: как обеспечить “фрагментацию” файла тестирования? Если создать последовательный, упорядоченный файл просто: запускай IOmeter на пустом диске – вот он и создаст свой iobw.tst, то с фрагментацией “на заказ” сложнее.
Для того, чтобы сделать фрагментированный файл я нашел любопытную утилитку, под названием MyDefragmenter, которая, как ясно из названия – дефрагментатор. Но у нее в комплекте есть также программка MyFragmenter :). Она делает вполне ожидаемую из названия вещь :)
Я взял созданный IOmeter тестовый файл и качественно замесил его с помощью этой утилитки. Я фрагментировал с ее помощью этот файл на 250 тысяч кусочков по 64KB каждый (ну, чтоб не было претензий, что гранаты у нас не той системы;), а потом повторно провел тестирование описанными выше паттернами.
Также я проанализировал ситуацию с фрагментацией не только файла на NTFS, но и в WAFL, а затем измерил эффект от работы reallocate в WAFL.
Хочу отдельно отметить, что в данном случае измеренные “попугаи” не могут рассматриваться по абсолютной величине, я не проводил никакого (необходимого) тюнинга системы, и настройки ее “по уму” и по best practices (это я сделаю позже, ту у меня есть некоторые бюрократические процедуры для этого). Целью теста было сравнить два достигнутых параметра производительности: “А” и”Б”, то есть их соотношение, а не достижение абсолютного рекорда, поэтому реплики с мест “чота как-то иопсев маловата!” мы отметем как неорганизованные ;).
Вот какие результаты я получил:
[VM-initial-contiguous-state] [ramp-up] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache [starting test: 10 min from beginning] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache [after 15 min of test] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache [finish 30 min of test] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache –
in out read write read write age
59% 8469 0 0 16340 23734 26540 23808 0 0 49s
58% 8403 0 0 15951 23798 26476 25972 0 0 49s
60% 8634 0 0 16875 23979 27100 26656 0 0 50s
60% 8940 0 0 17524 24786 26952 25600 0 0 50s
59% 8518 0 0 16531 23780 26200 21140 0 0 51s
73% 7420 0 0 14155 21114 24678 23500 0 0 52s
93% 6721 0 0 13053 18576 21729 22283 0 0 52s
in out read write read write age
84% 6296 0 0 12053 17708 21164 21356 0 0 58s
87% 6626 0 0 12627 18662 21784 22264 0 0 58s
56% 7773 0 0 15366 21460 24116 25608 0 0 59s
56% 7992 0 0 15547 22282 24344 23552 0 0 59s
56% 7609 0 0 14877 21145 23552 24652 0 0 59s
55% 7904 0 0 15507 21925 24520 23552 0 0 59s
in out read write read write age
50% 6947 0 0 13300 19589 21792 22304 0 0 1
53% 7107 0 0 13716 19946 22120 21376 0 0 1
49% 7152 0 0 13541 20323 22216 11672 0 0 1
49% 7221 0 0 13806 20392 22072 24 0 0 1
53% 7293 0 0 14059 20528 22524 2794 0 0 1
99% 5265 0 0 10141 14766 17919 40182 0 0 1
64% 6603 0 0 12549 18560 21603 22357 0 0 1
48% 6537 0 0 12832 18125 19492 19584 0 0 1
in out read write read write age
68% 6305 0 0 12071 17845 20643 22980 0 0 1
99% 5446 0 0 10335 15399 17551 22568 0 0 1
55% 7032 0 0 13896 19289 21480 20164 0 0 1
51% 6657 0 0 12933 18608 20668 22920 0 0 1
72% 6426 0 0 12237 18150 20240 22204 0 0 1
52% 6820 0 0 13055 19230 21452 22016 0 0 1
Summary Statistics ( 2306 samples 0 secs/sample)
CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache
in out read write read write age
Min
0% 0 0 0 1 0 4 0 0 0 0s
Avg
58% 7079 0 0 13690 19819 22136 20414 0 0 1
Max
99% 9116 0 0 18031 25295 28900 63498 0 0 1
Далее я запустил фрагментатор, который после нескольких часов работы создал мне почти идеально фрагментированный файл тестирования IOmeter (iobw.tst), размером 16TB, разделенный на 250 тысяч фрагментов
?? провел те же тесты:
Предварительно измерим состояние WAFL
>reallocate measure /vol/ds_fast Allocation check on ‘/vol/ds_fast’ is 23, hotspot 0 (threshold 4), consider running reallocate.
Все плохо, “23” это довольно сильная фрагментация, я, вдобавок, не реаллоцировал данные на томе после предыдущего получаса интенсивных записей.
[VM-2ndphase-fragmented-noncontiguous-state] [ramp-up] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache [start of test 10 min] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache [end of test 30 min] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache – Allocation check on ‘/vol/ds_fast’ is 37, hotspot 0 (threshold 4), consider running reallocate.
in out read write read write age
58% 8667 0 0 16723 24273 20112 22536 0 0 28s
56% 8503 0 0 16512 23753 20100 28192 0 0 28s
59% 8296 0 0 16388 22890 18944 39764 0 0 27s
57% 8369 0 0 16307 23297 19772 25472 0 0 26s
56% 8341 0 0 16129 23334 19576 32408 0 0 26s
58% 8847 0 0 17132 24760 20416 4384 0 0 27s
in out read write read write age
47% 6516 0 0 12565 18286 17444 23584 0 0 1
49% 6434 0 0 12543 17940 16624 28832 0 0 1
42% 6568 0 0 12691 18432 17416 0 0 0 1
80% 6010 0 0 11815 16629 15881 39465 0 0 1
94% 5768 0 0 11144 16082 16324 22250 0 0 1
47% 6864 0 0 13629 18887 17496 21000 0 0 1
in out read write read write age
43% 6383 0 0 12416 17813 18672 24 0 0 1
75% 5556 0 0 10910 15416 17714 37909 0 0 1
99% 5191 0 0 9787 14718 16491 21065 0 0 1
50% 6132 0 0 12082 16920 17922 22018 0 0 1
45% 6050 0 0 11886 16791 17936 22016 0 0 1
45% 5950 0 0 11346 16849 18020 21832 0 0 1
Summary Statistics ( 2597 samples 0 secs/sample)
CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache
in out read write read write age
Min
0% 0 0 0 0 0 0 0 0 0 0s
Avg
50% 5898 0 0 11419 16509 16151 20626 0 0 4
Max
99% 9301 0 0 18077 26100 23728 87549 0 0 >60
В процессе теста, характеризующегося интенсивной записью в тестовый файл, величина фрагментированности на уровне WAFL еще подросла, и составила 37 внутрионтаповских попугая.
Затем я решил проверить то, какое влияние оказывает пресловутая “фрагментация WAFL”, и после отработки второго теста я запустил reallocate start –f /vol/testvol и дождался, пока реаллокация блоков WAFL будет закончена (как видите ниже, она не идеальна, остановилась на “9”, но все же лучше чем была), а затем запусил тест на по-прежнему “фрагментированном” на уровне NTFS файле.
[VM-3rdphase-fragmented-contiguous-state] Allocation check on ‘/vol/ds_fast’ is 9, hotspot 0 (threshold 4), consider running reallocate. DSB-NETAPP2> reallocate status -v /vol/ds_fast [ramp-up] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache [beginning of test] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache [end of test] CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache –
Reallocation scans are on
/vol/ds_fast:
State: Idle
Flags: whole_vol,measure_only,repeat
Threshold: 4
Schedule: n/a
Interval: 1 day
NextRun: Fri Oct 19 11:01:16 SGT 2012
Optimization: 9
Measure Log: n/a
in out read write read write age
56% 7769 0 0 15198 21572 23137 24943 0 0 55s
54% 7617 0 0 14298 21749 23772 26776 0 0 55s
55% 7384 0 0 14346 20632 21996 30632 0 0 54s
57% 8169 0 0 16216 22459 23572 28296 0 0 54s
56% 7532 0 0 14507 21124 22960 28312 0 0 54s
57% 7821 0 0 15236 21811 23320 26880 0 0 54s
54% 7908 0 0 15333 22097 23948 18324 0 0 54s
in out read write read write age
72% 6989 0 0 13550 19434 21184 21846 0 0 59s
53% 7385 0 0 14268 20693 22896 21376 0 0 59s
53% 7258 0 0 14200 20176 21572 22144 0 0 59s
53% 7370 0 0 14210 20699 22360 22068 0 0 59s
54% 7446 0 0 14269 21031 22625 22633 0 0 59s
54% 7670 0 0 15007 21295 22448 22272 0 0 59s
54% 7360 0 0 14119 20686 22318 21123 0 0 58s
in out read write read write age
51% 6652 0 0 12674 18838 20464 22280 0 0 1
45% 6475 0 0 12417 18228 19936 2188 0 0 1
47% 6653 0 0 12913 18593 20432 36 0 0 1
96% 5249 0 0 10205 14650 17732 50947 0 0 1
82% 6035 0 0 11746 16749 19777 22056 0 0 1
47% 6371 0 0 12104 18062 20408 20768 0 0 1
50% 6664 0 0 12870 18699 20228 22739 0 0 1
Summary Statistics ( 2324 samples 0 secs/sample)
CPU NFS CIFS HTTP Net kB/s Disk kB/s Tape kB/s Cache
in out read write read write age
Min
0% 0 0 0 0 0 0 0 0 0 0s
Avg
57% 6664 0 0 12893 18658 20621 22416 0 0 58s
Max
99% 8304 0 0 16329 23168 25024 157234 0 0 1
Как видите, производительность на “реаллоцированном”, но фрагментированном файле фактически вернулась к показателям нефрагментированного, свежесозданного файла, что убедительно показывает, что основной вклад в некоторое падение производительности при активной перезаписи вносит именно “фрагментация WAFL”, и после отработки на системе хранения reallocate производительность работы с чудовищно и намеренно фрагментированного файла (25 тысяч фрагментов, разбросанных по диску! В реальной жизни вы такого, уверен, не получите никогда) возвращается к уровню нефрагментированного файла.
Выводы и lessons learned:
Фрагментация данных на диске прикладной системы, лежащей на NetApp, не играет существенной роли роли и не приводит к снижению производительности не только при 100% random, но и при, в значительной мере, смешанном профиле, со значительным (до 40%) секвентальным компонентом. Некоторый наблюдаемый эффект снижения показателей производительности вызывается non-contiguous allocate блоков WAFL, что, вероятно, мешает правильному их кэшированию и read-ahead. Тем не менее даже при ОЧЕНЬ сильно искусственно проявленном эффекте (с уровнем, которого вы никогда в реальной жизни не достигнете) это снижение не превышает 17% от пиковой производительности (снизилась с 7079 до 5898) и достаточно эффективно парируется процедурой WAFL reallocate, работающей как по расписанию, так и при превышении порога. WAFL reallocate, отдельно отмечу, никак не упорядочивает фрагментированный уровнем выше файл на файловой системе поверх WAFL, который остается фрагментированным, а работает только со структурами самого WAFL. Разница на реаллоцированном томе с очень сильно фрагментированным файлом и реаллоцированном, но дефрагментированным, непрерывным (на уровне файловой системы хоста) составляет, как можно видеть выше, менее 8%.
Сим считаю в данном блоге вопрос “влияет ли при практической эксплуатации системы хранения NetApp фрагментация файлов на производительность работы с ними” закрытым: нет, не влияет.
Хороший труд.
Что подробнее почитать по reallocate? можно из netapp источников, логин есть.
Не совсем понимаю что это и как работает.
Я уже года два собираюсь написать все, что удалось разрыть по поводу reallocate, но все собираюсь.
Проблема внутренних ресурсов NetApp в том, что до определенных источников имеют доступ люди, обладающие только определенным уровнем посвящения, и я лично далек от высших, поэтому что-то для меня остается скрытым :) Но что-то разобрать удалось. Может таки соберусь и напишу, но попозже. Но в этом году, обещаю. :)
Роман, а если выделить не 40ГБ диск для хранения 16ГБ тестового файла, а 17ГБ?
?? ещё вопрос какой размер датасторе выделялся на NetApp? По хорошему, при выполении тестирования его заполненность должна быть близка к 80-90%.
Киселев Сергей:
> По хорошему
По хорошему для кого?
Я считаю, что тестирование должно давать релевантные решаемой задаче результаты, чтобы его результаты можно было использовать для оценки.
Я не считаю, что тестирование во что бы то ни стало должно демонстрировать максимально плохой, из всех возможных, результат, измеренный в наихудших из возможных условиях. Я считаю, что измерять надо в близких к реальным условиях, по крайней мере соответствующих рекомендованным производителем best practices.
Тогда результат будет иллюстрировать практически достижимые показатели, в реально применимых условиях.
Переводя на любимые в этом блоге автомобильные аналогии: можно нагрузить весь салон легковушки кирпичами, включить первую передачу и втопить газ в пол. Но будет ли полученный результат релевантен задачам легковушки, и что полученный таким образом результат покажет?
> при выполении тестирования его заполненность должна быть близка к 80-90%.
Кому она это должна?
Былобы неплохо знать версию датаонтапа на ваших файлерах.
bbk:
8.1.1 GA
А как на счет значений для latency, было бы интересно это знать, ??МХО нет смысле в 7K IOPS при, скажем, 50ms latency.
> Кому она это должна?
То, что фрагментация не влияет на производительность при относительно хороших условиях это не так интересно.
??нтересно когда она начинает деградировать.
Заполненность агрегатов на 90-95% это часто данность, с которой нужно жить продолжительное время, без возможности её снизить.
Какая будет производительность в таких условиях?
Peter Sergeev:
> Заполненность агрегатов на 90-95% это часто данность, с которой нужно жить
Работа в нерекомендованных производителем режимах - это плохая “данность”, и bad practice.
Роман,
условия, при которых проводилось тестирование, мало применимы на практике и поэтому мало интересны Заказчику. Было бы интереснее увидеть как поведет себя система в более сложных ситуациях, которые, как ни странно, чаще встречаются в жизни, чем описанные в Best Practices.
Киселев Сергей:
Сергей, если пользователь игнорирует вендорские рекомендации, то он, конечно, в своем праве, но сам себе злобный буратино. Довольно бессмысленно требовать от вендора испытания микроскопа в качестве инструмента для заколачивания гвоздей, просто потому что покупателю так хочется столь странным способом его использовать. на то и пишутся вендорские Best Practices, чтобы ими руководствоваться при создании системы, а если есть какие-то партнеры, или интеграторы, или конечные пользователи, которые их прямо и осознанно нарушают, руководствуясь какими-то своими представлениями о “правильности”, то нам с такими не по пути :)
А можно узнать значение latency в мс при всех этих тестах? На хосте и на самой СХД. ?? размер очереди тоже был бы полезен. Нигде не указано… Если использовался Iometer, то там это видно.
Обязательно, как-то я этот момент пропустил в статье, но сейчас данные не под руками, а на следующей неделе я дополню пост. Latency ухудшается, конечно, но не катастрофически.