Про ZFS L2ARC

В хорошую погоду zpool iostat -v zdata 5 выглядит теперь так

Но на самом деле, все как-то хуже. Не сильно, но все-таки.

Вот тут случился accidental reboot и я на пустом кэше попробовал так

tar cf /dev/null some-75Gb-folder

Ну и смотрю на скорости (на самом деле там tar cf - .. | mbuffer -s 16k -o /dev/null чтобы скорости видеть):

  • Первый проход: ~650MB/sec (ну так диски отдали), в L2ARC легла ~половина (и что-то в ARC)
  • Второй раз - 750, OK
  • А дальше началось через раз:
    • >1GB/sec и диски практически не трогаются
    • ~750-850Mb/sec и с дисков читается процентов 10-15 (на глазок), остальное из кэшей.

Не понимаю. Файлы не меняются эти,  а вот такая вот фигня.

Этот самый ~1Gb/sec - это столько примерно, сколько умеет кэш отдавать (Patriot Hellfire).

Настройки такие:

vfs.zfs.l2arc_norw=0
vfs.zfs.l2arc_noprefetch=0
vfs.zfs.l2arc_write_max=838860800
vfs.zfs.l2arc_write_boost=838860800

Впрочем, если не скорости мерять, а смотреть на реальную работу, то после прогрева рабочего каталога наступает счастье, даже не столько в bandwidth (даже полгигабайта/сек употребить - проблема), сколько в latency, то же большое количество превьюшек строится быстро. Не так быстро, как с локального SSD, но вполне вот удовлетворительно (конечно, если нужны только превьюшки, то спасал и просто ARC, но он размывался довольно легко). И тихо, диски в NAS не грохочут в процессе.

Пожалуй, это вторые  по важности вложенные в  NAS $250 после 10G (у меня тут вдруг десктоп пошел к ящику по гигабиту, этот ж ужас, как можно так жить...)

Comments

В зависимости от "старости" обращений к ... - либо читаем из кэша не глядя, либо сверяем "явки и пароли" (чек_суммы и пр.), либо честно перечитываем ...

Уверен, что Вы не служили, но ТЕМ НЕ МЕНЕЕ, поздравляю Вас с универсальным МУЖСКИМ праздником.

Чексуммы, по идее, сверяются всегда на zfs.

Возможно я неправильно понимаю или написана какая-то глупость. Данные на диски попасть мимо включённого кэша не могут, поэтому в кэше всегда актуальные данные и они не могут "протухнуть". Тогда "либо читаем из кэша не глядя, либо сверяем "явки и пароли" (чек_суммы и пр.), либо честно перечитываем ..." лишено всякого смысла. Если метаданные/данные есть в кэше читаем из него, иначе читаем с дисков :-).

Нет ли там искусственного разума "если кэш кажется нам медленным, то для стримовой нагрузки читанем еще и с блинов" ?

Вот строго через раз получается наутро:

$ tar cf - folder | mbuffer -s 16k -o /dev/null
summary: 79.0 GiByte in  1min 50.2sec - average of  733 MiB/s
$ tar cf - folder | mbuffer -s 16k -o /dev/null
summary: 79.0 GiByte in  1min 12.7sec - average of 1112 MiB/s
$ tar cf - folder | mbuffer -s 16k -o /dev/null
summary: 79.0 GiByte in  1min 45.1sec - average of  769 MiB/s
$ tar cf - folder | mbuffer -s 16k -o /dev/null
summary: 79.0 GiByte in  1min 11.9sec - average of 1125 MiB/s

 

При этом 700+ - с блинов читается процентов 10 (на глаз), 1100+ - соответственно 0.

Последний раз подходил к l2arc в момент http://blog.lexa.ru/2016/07/24/zfs_l2arc_performance.html. Там у меня и у тебя тоже наблюдалась подобная "скачущая" картинка. Поэтому похоже на "закономерность". Так как l2arc_noprefetch=0, то "искусственный разум" с моей колокольни маловероятен. Природа сего "явления" мне неизвестна, тем более через раз :-). Если очень хочешь разобраться, то я в первую очередь проверил бы - сколько он пишет в l2arc через раз. А так, да - падение на 30% при чтение 10% с hdd напрягает.

Пишет, в первом приближении "ничего" (смотрю по zpool iostat -v). Т.е. да, что-то пишется в L2ARC, но по порядку величины это - доли процента о того, что читается с блинов (это может быть просто вытеснение из ARC чего-то другого, у меня ж система живая, хоть под копеечной, но под нагрузкой).

UPD: нагрузка на этот dataset создается только моей WS и в моменты тестов там если что и "было", то совершенно грошовое, очень близкое к нулю. А вот ARC - вестимо общий с бэкапным dataset, куда со всего дома бэкапятся в какие-то моменты.

Посмотрел сегодня arc.c. Далее только комментарии:
...
* At this point, we have a level 1 cache miss. Try again in
* L2ARC if possible.
...
* Read from the L2ARC if the following are true:
* 1. The L2ARC vdev was previously cached.
* 2. This buffer still has L2ARC metadata.
* 3. This buffer isn't currently writing to the L2ARC.
* 4. The L2ARC entry wasn't evicted, which may
* also have invalidated the vdev.
* 5. This isn't prefetch and l2arc_noprefetch is set.
Твои настройки не запрещают ни один из пунктов.
...
Начиная с 5775 строки, как мне кажется, самый важный комментарий для твоего случая. Желательно его прочитатать полностью. Приведу только, что меня заинтересовало:
...
* Read requests are satisfied from the following sources, in order:
*
* 1) ARC
* 2) vdev cache of L2ARC devices
* 3) L2ARC devices
* 4) vdev cache of disks
* 5) disks
*
* Some L2ARC device types exhibit extremely slow write performance.
* To accommodate for this there are some significant differences between
* the L2ARC and traditional cache design:
*
* 1. There is no eviction path from the ARC to the L2ARC. Evictions from
* the ARC behave as usual, freeing buffers and placing headers on ghost
* lists. The ARC does not send buffers to the L2ARC during eviction as
* this would add inflated write latencies for all ARC memory pressure.
*
* 2. The L2ARC attempts to cache data from the ARC before it is evicted.
* It does this by periodically scanning buffers from the eviction-end of
* the MFU and MRU ARC lists, copying them to the L2ARC devices if they are
* not already there. It scans until a headroom of buffers is satisfied,
* which itself is a buffer for ARC eviction. If a compressible buffer is
* found during scanning and selected for writing to an L2ARC device, we
* temporarily boost scanning headroom during the next scan cycle to make
* sure we adapt to compression effects (which might significantly reduce
* the data volume we write to L2ARC). The thread that does this is
* l2arc_feed_thread(), illustrated below; example sizes are included to
* provide a better sense of ratio than this diagram:
...
* 3. If an ARC buffer is copied to the L2ARC but then hit instead of
* evicted, then the L2ARC has cached a buffer much sooner than it probably
* needed to, potentially wasting L2ARC device bandwidth and storage. It is
* safe to say that this is an uncommon case, since buffers at the end of
* the ARC lists have moved there due to inactivity.
*
* 4. If the ARC evicts faster than the L2ARC can maintain a headroom,
* then the L2ARC simply misses copying some buffers. This serves as a
* pressure valve to prevent heavy read workloads from both stalling the ARC
* with waits and clogging the L2ARC with writes. This also helps prevent
* the potential for the L2ARC to churn if it attempts to cache content too
* quickly, such as during backups of the entire pool.
*
* 5. After system boot and before the ARC has filled main memory, there are
* no evictions from the ARC and so the tails of the ARC_mfu and ARC_mru
* lists can remain mostly static. Instead of searching from tail of these
* lists as pictured, the l2arc_feed_thread() will search from the list heads
* for eligible buffers, greatly increasing its chance of finding them.
*
* The L2ARC device write speed is also boosted during this time so that
* the L2ARC warms up faster. Since there have been no ARC evictions yet,
* there are no L2ARC reads, and no fear of degrading read performance
* through increased writes.
*
* 6. Writes to the L2ARC devices are grouped and sent in-sequence, so that
* the vdev queue can aggregate them into larger and fewer writes. Each
* device is written to in a rotor fashion, sweeping writes through
* available space then repeating.
*
* 7. The L2ARC does not store dirty content. It never needs to flush
* write buffers back to disk based storage.
*
* 8. If an ARC buffer is written (and dirtied) which also exists in the
* L2ARC, the now stale L2ARC buffer is immediately dropped.
...
Осталось выработать гипотезу и придумать как её проверить :-).

Я прочитал (целиком комментарий, не только цитату).

Гипотеза получается странная, вот с середины теста (быстрый прогон).
- L2ARC - 90% (условная цифра), ARC - 10%. Блины не трогаем. читаем все с SSD+RAM.
- в процессе этого чтения, мы вытесняем все из ARC, но так, что оно не пишется в L2
- и следующий тест читает 10% уже с блинов. Эти 10% оказываются в ARC, их не вытесняет.
- на колу мочало, начинай с начала.

Но, блин.

Странная - не странная, но она мне тоже пришла в голову :-). Только думаю не 10%, а наверно побольше и наверно эта цифра всё таки постепенно уменьшается. Если картинка ещё повторяется, то стоит ещё добавить между прогонами iostat -Ix и показать значения для l2arc-диска. Думаю по объёму прочитанных данных с него, может всё и прояснится :-).

zpool iostat нормально ж показывает что там читается с L2.
Интересно будет попробовать с ограничением скорости прогрева. Так, по идее, если мы читаем медленно, то может помочь.

Я буду тут когда-то (в марте) электричество перекладывать, вот на пустом L2 тогда и попробую

А какая разница на пустом или заполненном? Важно только на повторяющейся картинке увидеть объём считанных данных с l2arc-диска при тестовом прогоне, сравнить с общим прочитанным объёмом и посмотреть на динамику изменения при следующих прогонах.

Меня волнует, скорее, рецепт "как заполнить". Во всяком случае, попробовать медленное чтение явно стоит.

А про объем - это попытка понять "сколько взялось из ARC" ? (все что не с блинов и не с SSD)

Если объём считывания из l2arc-диска не изменяется (или даже увеличивается от раза к разу), а скорость скачет, то гипотеза верна. А если известна причина, то можно поискать решение :-). На счёт медленного чтения у меня пока больше сомнений.

Другое умозрительное решение - это добиться ARC eviction. Путем чтения FS у которой secondarycache=metadata

P.S. перебутил тут ящик, руки чесались там диски переключить из daN в adaN, если вечером будет время - буду мерять IO.

Это ведь зависит от заложенной логики...

Ну так как l2arc имеет право отвалиться в любую секунду - логика должна быть такой.

Этот самый ~1Gb/sec - это столько примерно, сколько умеет кэш отдавать (Patriot Hellfire).
Почему 1Gb? Он же вроде по спецификации должен 3 отдавать?

Интересная картинка
https://3dnews.ru/assets/external/illustrations/2016/09/26/939978/graph-...

С vfs.zfs.vdev.max_pending игрались? Или как ещё в ZFS можно регулировать QD?

Я как-то боюсь, что при чтении из кэша - особо и никак.

Оно и не надо особо, с учетом скорости сети, гигабайт - в самый раз.

Если ещё актуальна идея - записывать всё, что выталкивается из arc в l2arc, то стоит обратить внимание на vfs.zfs.l2arc_feed_min_ms и vfs.zfs.l2arc_headroom.

Add new comment