Анализ памяти Jemalloc
По умолчанию Doris использует Jemalloc в качестве универсального аллокатора памяти. Память, занимаемая самим Jemalloc, включает Cache и Metadata. В Cache входят Thread Cache и Dirty Page. Исходный профиль аллокатора памяти можно просмотреть в реальном времени в разделе Профили Jemalloc, расположенном в разделе Информация о памяти на веб-странице профиля процесса Doris BE по адресу http://{be_host}:{be_web_server_port}/profile.
Анализ памяти Jemalloc Cache
Если у трекера памяти Label=tc/jemalloc_cache, Type=overview большое значение, это означает, что Cache в Jemalloc или TCMalloc занимает много памяти. Doris использует Jemalloc в качестве аллокатора по умолчанию, поэтому здесь рассматривается только ситуация, когда много памяти занимает Jemalloc Cache.
MemTrackerLimiter Label=tc/jemalloc_cache, Type=overview, Limit=-1.00 B(-1 B), Used=410.44 MB(430376896 B), Peak=-1.00 B(-1 B)
До Doris 2.1.6 в
Label=tc/jemalloc_cacheтакже учитывается Jemalloc Metadata, и причиной слишком большого значенияLabel=tc/jemalloc_cacheвполне может быть большой объём памяти, занимаемой Jemalloc Metadata. См. анализ трекера памятиLabel=tc/jemalloc_metadata.
Во время работы процесса BE Jemalloc Cache состоит из двух частей.
-
Thread Cache: кеширует заданное количество страниц. См. Jemalloc opt.tcache.
-
Dirty Page: все страницы памяти в Arena, которые можно использовать повторно.
Как просмотреть Jemalloc Cache
Чтобы получить профиль Jemalloc, откройте раздел Профили Jemalloc в разделе Информация о памяти на веб-странице профиля процесса Doris BE по адресу http://{be_host}:{be_web_server_port}/profile (значение webserver_port по умолчанию: 8040). Использование Jemalloc Cache можно оценить по нескольким ключевым показателям.
-
tcache_bytesв профиле Jemalloc показывает общий объём Jemalloc Thread Cache в байтах. Большое значениеtcache_bytesозначает, что Jemalloc Thread Cache занимает слишком много памяти. -
Большая сумма значений столбца
dirtyв таблицеextentsпрофиля Jemalloc указывает на то, что Jemalloc Dirty Page занимает слишком много памяти.
Thread Cache занимает слишком много памяти
Возможно, в Thread Cache кешируется много больших страниц, поскольку его верхний предел задаётся количеством страниц, а не их суммарным размером в байтах.
Попробуйте уменьшить значение lg_tcache_max в JEMALLOC_CONF в файле be.conf. Параметр lg_tcache_max задаёт верхний предел размера страницы в байтах, допускаемого к кешированию. Значение по умолчанию составляет 15, то есть 32 KB (2^15). Страницы большего размера не кешируются в Thread Cache. Параметр lg_tcache_max соответствует показателю Maximum thread-cached size class в профиле Jemalloc.
До Doris 2.1 значение
lg_tcache_maxпо умолчанию вJEMALLOC_CONFв файлеbe.confсоставляет 20, что в некоторых сценариях приводит к чрезмерному размеру Jemalloc Cache. После Doris 2.1 его вернули к стандартному для Jemalloc значению 15.
Обычно это происходит потому, что запрос или загрузка в процессе BE запрашивает много страниц памяти крупных классов размеров, либо потому, что после выполнения запроса или загрузки с большим потреблением памяти в Thread Cache остаётся много таких страниц. Очистка Thread Cache выполняется в двух случаях. Первый: когда число операций выделения и освобождения памяти достигает определённого значения, освобождаются блоки памяти, которые давно не использовались. Второй: при завершении потока освобождаются все страницы. Здесь возможен неблагоприятный сценарий. Если поток больше не выполняет новых запросов или загрузок, он перестаёт выделять память и переходит в так называемое состояние idle. Пользователи ожидают, что после завершения запроса память будет освобождена, но в этом сценарии Thread Cache не очищается, пока поток не завершится.
Однако обычно следить за Thread Cache не требуется. Когда процессу не хватает доступной памяти, а размер Thread Cache превышает 1G, Doris принудительно очищает Thread Cache.
Dirty Page занимает слишком много памяти
extents: size ind ndirty dirty nmuzzy muzzy nretained retained ntotal total
4096 0 7 28672 1 4096 21 86016 29 118784
8192 1 11 90112 2 16384 11 90112 24 196608
12288 2 2 24576 4 49152 45 552960 51 626688
16384 3 0 0 1 16384 6 98304 7 114688
20480 4 0 0 1 20480 5 102400 6 122880
24576 5 0 0 43 1056768 2 49152 45 1105920
28672 6 0 0 0 0 13 372736 13 372736
32768 7 0 0 1 32768 13 425984 14 458752
40960 8 0 0 31 1150976 35 1302528 66 2453504
49152 9 4 196608 2 98304 3 139264 9 434176
57344 10 0 0 1 57344 9 512000 10 569344
65536 11 3 184320 0 0 6 385024 9 569344
81920 12 2 147456 3 241664 38 2809856 43 3198976
98304 13 0 0 1 86016 6 557056 7 643072
114688 14 1 102400 1 106496 15 1642496 17 1851392
Уменьшите значение dirty_decay_ms в JEMALLOC_CONF в файле be.conf до 2000 мс или меньше. Значение dirty_decay_ms по умолчанию в be.conf составляет 5000 мс. Jemalloc освобождает грязные страницы по плавной кривой в течение времени, заданного параметром dirty_decay_ms. Подробнее см. Jemalloc opt.dirty_decay_ms. Когда процессу BE не хватает доступной памяти и запускается Minor GC или Full GC, он активно освобождает все грязные страницы в соответствии с определённой стратегией.
До Doris 2.1 значение
dirty_decay_msпо умолчанию вJEMALLOC_CONFв файлеbe.confсоставляет 15000, что в некоторых сценариях приводит к чрезмерному размеру Jemalloc Cache. После Doris 2.1 значение по умолчанию составляет 5000.
Раздел extents профиля Jemalloc содержит статистику по группам страниц разного размера во всех arena Jemalloc, где ndirty обозначает количество грязных страниц, а dirty обозначает их общий объём памяти. См. описание stats.arenas.<i>.extents.<j>.{extent_type}_bytes в документации Jemalloc. Чтобы получить объём памяти Dirty Page в Jemalloc в байтах, сложите значения dirty для всех размеров страниц.
Анализ памяти Jemalloc Metadata
Если у трекера памяти Label=tc/jemalloc_metadata, Type=overview большое значение, это означает, что Metadata в Jemalloc или TCMalloc занимает много памяти. Doris использует Jemalloc в качестве аллокатора по умолчанию, поэтому здесь рассматривается только ситуация, когда много памяти занимает Jemalloc Metadata.
MemTrackerLimiter Label=tc/jemalloc_metadata, Type=overview, Limit=-1.00 B(-1 B), Used=144 MB(151759440 B), Peak=-1.00 B(-1 B)
Трекер памяти
Label=tc/jemalloc_metadataбыл добавлен после Doris 2.1.6. Ранее Jemalloc Metadata учитывалась в трекере памятиLabel=tc/jemalloc_cache.
Как просмотреть Jemalloc Metadata
Профиль Jemalloc можно получить в разделе Профили Jemalloc, расположенном в разделе Информация о памяти на веб-странице профиля процесса Doris BE по адресу http://{be_host}:{be_web_server_port}/profile (значение webserver_port по умолчанию: 8040). Найдите в профиле Jemalloc общую статистику использования памяти, показанную ниже. В ней metadata обозначает объём памяти Jemalloc Metadata.
Allocated: 2401232080, active: 2526302208, metadata: 535979296 (n_thp 221), resident: 2995621888, mapped: 3221979136, retained: 131542581248
-
Allocated: общий объём памяти в байтах, выделенной Jemalloc для процесса BE. -
active: общий объём всех страниц в байтах, выделенных Jemalloc для процесса BE. Он кратен размеру страницы и обычно больше или равенAllocated. -
metadata: общий объём метаданных Jemalloc в байтах. Он зависит от количества выделенных и кешированных страниц, фрагментации памяти и других факторов. См. документацию Jemalloc stats.metadata -
retained: размер отображений виртуальной памяти, удерживаемых Jemalloc. Эта память не возвращается операционной системе через munmap или аналогичные механизмы и не имеет тесной связи с физической памятью. См. документацию Jemalloc stats.retained
Jemalloc Metadata занимает слишком много памяти
Объём Jemalloc Metadata растёт с увеличением объёма виртуальной памяти процесса. Обычно большой объём виртуальной памяти процесса Doris BE объясняется тем, что Jemalloc удерживает множество отображений виртуальной памяти, то есть упомянутый выше retained. Виртуальная память, возвращённая Jemalloc, по умолчанию кешируется в Retained в ожидании повторного использования и не освобождается ни автоматически, ни вручную.
Основная причина большого объёма Jemalloc Retained заключается в недостаточном повторном использовании памяти на уровне кода Doris. Из-за этого приходится запрашивать большой объём виртуальной памяти, которая после освобождения попадает в Jemalloc Retained. Обычно отношение объёма виртуальной памяти к объёму Jemalloc Metadata находится в пределах 300-500. То есть при объёме виртуальной памяти 10T Jemalloc Metadata может занимать 20G.
Если Jemalloc Metadata и Retained продолжают расти, а объём виртуальной памяти процесса становится слишком большим, рекомендуется рассмотреть регулярный перезапуск процесса Doris BE. Обычно это происходит только после длительной работы Doris BE и встречается лишь в небольшом числе кластеров Doris. В настоящее время уменьшить объём отображений виртуальной памяти, удерживаемых Jemalloc Retained, без потери производительности невозможно. В Doris постоянно ведётся работа по оптимизации использования памяти.
Если описанные выше проблемы возникают часто, воспользуйтесь следующими способами.
-
Радикальное решение: отключить кеширование отображений виртуальной памяти в Jemalloc Retained. Для этого добавьте
retain:falseпослеJEMALLOC_CONFв файлеbe.confи перезапустите BE. Однако производительность запросов может значительно снизиться: производительность в тесте TPC-H Benchmark уменьшится примерно в 3 раза. -
В Doris 2.1 можно отключить Pipelinex и Pipeline, выполнив
set global experimental_enable_pipeline_engine=false; set global experimental_enable_pipeline_x_engine=false;, поскольку pipelinex и pipeline запрашивают больше виртуальной памяти. Это также приведёт к снижению производительности запросов.