Об утилите cachestat я узнал из статьи Brendan Gregg - Analyzing a High Rate of Paging.
В ней расследуются причины аномально долгого процессинга файлов размером в 100Gbytes, тогда как файлы в 40Gbytes обрабатывались на несколько порядков быстрее.
В том кейсе точно поставить диагноз - большой объект не помещался в кеш, что приводило к trashing’у страниц памяти, автору помог инструмент cachestat
.
Если в кратце, то утилита подсчитывает соотношение попаданий в кеш файловой системы относительно общего числа операций на чтение - cache hit ratio:
# cachestat
HITS MISSES DIRTIES HITRATIO BUFFERS_MB CACHED_MB
1132 0 4 100.00% 277 4367
161 0 36 100.00% 277 4372
16 0 28 100.00% 277 4372
17154 13750 15 55.51% 277 4422
19 0 1 100.00% 277 4422
На всякий случай напомню, что каждый промах чреват мажорным Page Fault, что приводит чтению с диска, а это явная деградация производительности, которую хочется избегать.
На мой взгляд значение HITRATIO
может явным образом подсвечивать голодание системы по памяти, а значит полезно иметь его в виде метрики для постоянного отслеживания.
конкретный порог после которого надо бить тревогу подбирается опытным путем, но кмк все что ниже 85-90% стоит внимания.
К счастью в мой любимый ebpf_exporter cachestat
уже был портирован.
Но вот незадача - текущая версия разрабатывалась под ядра 5.16 и выше, а в них немного поломали API (1, 2), таким образом ядра < 5.16 остались за бортом, а например дефолтное ядро для debian 11 - 5.10.
Я добавил PR, решающий эту проблему - для версий ядер < 5.16 можно использовать cachestat-pre-kernel-5.16
, а для более свежих cachestat
плагин.
Так же попутно заменил трасировку kprobe
в пользу более быстрых kfunc
/tracepoint
(см.benchmark), что безусловно хорошо для промышленной эксплуатации.
PromQL
запрос:
(1 - (
sum by (instance) (ebpf_exporter_page_cache_ops_total{op="page_add_lru"})
-
sum by (instance) (ebpf_exporter_page_cache_ops_total{op="page_mark_dirties"})
)
/
(
sum by (instance) (ebpf_exporter_page_cache_ops_total{op="cache_access"})
-
sum by (instance) (ebpf_exporter_page_cache_ops_total{op="cache_writes"})
))
даст подобный незамысловатый график:
Удачи!