Есть ли способ обнаружить фрагментацию памяти в Linux? Это связано с тем, что на некоторых долго работающих серверах я заметил снижение производительности и только после перезапуска процесса я вижу лучшую производительность. Я заметил это больше при использовании поддержки огромных страниц linux - огромные страницы в linux более подвержены фрагментации?
В частности, я посмотрел / proc / buddyinfo. Я хочу знать, есть ли более эффективные способы (не только команды CLI как таковые, любая программа или теоретическое обоснование), чтобы посмотреть на это.
linux
linux-kernel
Рагу
источник
источник
vmstat
в полеso
?vmstat
является обычным пользовательским опытом. Если бы вы писали программу для того же, она была бы другой. Если вы собираетесь использовать bash для сбора этой информации, отредактируйте ваш вопрос, он не будет закрыт :)Ответы:
Я отвечаю на тег Linux . Мой ответ специфичен только для Linux .
Да, огромные страницы более подвержены фрагментации. Существует два вида памяти: тот, который получает ваш процесс (виртуальный), и тот, которым ядро управляет (реальный). Чем больше любая страница, тем сложнее будет сгруппировать (и сохранить ее) своих соседей, особенно когда ваш сервис работает в системе, которая также должна поддерживать другие, которые по умолчанию выделяют и записывают в память больше памяти, чем они. на самом деле в конечном итоге с помощью.
Отображение ядром (реальных) предоставленных адресов является закрытым. Существует очень веская причина, по которой пользовательское пространство видит их так, как их представляет ядро, потому что ядро должно иметь возможность выполнять перегрузку, не путая пользовательское пространство. Ваш процесс получает хорошее непрерывное адресное пространство «Disneyfied» для работы, не обращая внимания на то, что ядро фактически делает с этой памятью за кулисами.
Причина, по которой вы видите снижение производительности на долго работающих серверах, наиболее вероятна из-за того, что выделенные блоки, которые не были явно заблокированы (например,
mlock()
/mlockall()
илиposix_madvise()
) и не модифицированы в течение некоторого времени, были выгружены , что означает, что ваша служба переходит на диск, когда она должна прочитать их. Изменение этого поведения делает ваш процесс плохим соседом , поэтому многие люди размещают свои RDBMS на совершенно другом сервере, чем web / php / python / ruby / что угодно. Разумно, единственный способ исправить это - снизить конкуренцию за смежные блоки.Фрагментация действительно заметна (в большинстве случаев) только тогда, когда страница A находится в памяти, а страница B перемещена в область подкачки. Естественно, перезапуск вашего сервиса, похоже, «излечит» это, но только потому, что ядро еще не имело возможности вывести из процесса (в настоящее время) вновь выделенные блоки в пределах его коэффициента перегрузок.
Фактически, перезапуск (скажем, «apache») при высокой нагрузке, скорее всего, отправит блоки, принадлежащие другим сервисам, прямо на диск. Так что да, «apache» улучшится на короткое время, но «mysql» может пострадать… по крайней мере, пока ядро не заставит их страдать одинаково, когда просто не хватает достаточной физической памяти.
Добавьте больше памяти или разделите требовательных
malloc()
потребителей :) Это не просто фрагментация, на которую вам нужно смотреть.Попробуйте
vmstat
получить обзор того, что на самом деле хранится где.источник
ядро
Для получения текущего индекса фрагментации используйте:
Для дефрагментации памяти ядра попробуйте выполнить:
Также вы пытаетесь отключить прозрачные огромные страницы (иначе THP) и / или отключить обмен (или уменьшить
swappiness
).Местоположение пользователя
Чтобы уменьшить фрагментацию пользовательского пространства, вы можете попробовать другой распределитель, например
jemalloc
(он обладает большими возможностями самоанализа , что даст вам внутреннюю внутреннюю фрагментацию распределителя).Вы можете переключиться на пользовательский malloc, перекомпилировав с ним свою программу или просто запустив программу с
LD_PRELOAD
:LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app
(остерегайтесь взаимодействий между THP и распределителями памяти )Хотя, немного не связанный с фрагментацией памяти (но связанный с уплотнением / миграцией памяти), вы, вероятно, захотите запустить несколько экземпляров вашей службы, по одному для каждого узла NUMA, и связать их, используя
numactl
.источник
mmap
) по-разному реализованы в разных ядрах (например, Linux против FreeBSD) или даже в разных версиях одной и той же ОС (2.6.32 против 3.2 против 3.10) .. "Это позволяет изменять страницы [. ..] будет извлечен из [...] физической памяти "- это позволит скрыть утечки памяти. «обрабатывать случаи, когда зарезервировано гораздо больше памяти, чем используется» - медленная система намного хуже, чем неработающая система, поэтому «вменяемая» сомнительна.Использование огромных страниц не должно вызывать дополнительной фрагментации памяти в Linux; Поддержка огромных страниц в Linux предназначена только для разделяемой памяти (через shmget или mmap), и любые используемые огромные страницы должны быть специально запрошены и предварительно выделены системным администратором. Оказавшись в памяти, они там закреплены и не выгружены. Проблема обмена большими страницами перед лицом фрагментации памяти заключается именно в том, почему они остаются закрепленными в памяти (при выделении огромной страницы размером 2 МБ ядро должно найти 512 смежных свободных страниц объемом 4 КБ, которых может даже не быть).
Linux документация на огромных страницах: http://lwn.net/Articles/375098/
Существует одно обстоятельство, при котором фрагментация памяти может привести к медленному распределению огромных страниц (но не в том случае, когда огромные страницы вызывают фрагментацию памяти), и это в том случае, если ваша система настроена для увеличения пула огромных страниц по запросу приложения. Если / proc / sys / vm / nr_overcommit_hugepages больше, чем / proc / sys / vm / nr_hugepages, это может произойти.
источник
Есть
/proc/buddyinfo
что очень полезно. Это более полезно с хорошим форматом вывода, как этот скрипт Python может сделать:https://gist.github.com/labeneator/9574294
Для больших страниц вам нужны бесплатные фрагменты размером 2097152 (2MiB) или больше. Для прозрачных огромных страниц он автоматически сжимается, когда ядро запрашивает некоторые из них, но если вы хотите увидеть, сколько вы можете получить, выполните команду root:
Также да, огромные страницы вызывают большие проблемы для фрагментации. Либо вы не можете получить какие-либо огромные страницы, либо их присутствие заставляет ядро тратить много дополнительного времени, пытаясь получить их.
У меня есть решение, которое работает для меня. Я использую это на нескольких серверах и моем ноутбуке. Отлично работает на виртуальных машинах.
Добавьте
kernelcore=4G
опцию в вашу командную строку ядра Linux. На моем сервере я использую 8G. Будьте осторожны с числом, потому что оно не позволит вашему ядру распределять что-либо за пределами этой памяти. Серверы, которым требуется много буферов сокетов или потоковая запись на сотни дисков, не хотели бы ограничиваться таким образом. Любое распределение памяти, которое должно быть "закреплено" для плиты или прямого доступа к памяти, находится в этой категории.Вся остальная ваша память затем становится «подвижной», что означает, что она может быть сжата в красивые куски для огромного размещения страниц. Теперь прозрачные огромные страницы могут действительно работать и работать так, как они должны. Всякий раз, когда ядру нужно больше 2M страниц, оно может просто переназначить 4K страницы куда-нибудь еще.
И я не совсем уверен, как это взаимодействует с прямым вводом-выводом без копирования. Память в «подвижной зоне» не должна быть закреплена, но прямой запрос ввода-вывода сделает именно это для DMA. Это может скопировать это. В любом случае это может закрепить его в подвижной зоне. В любом случае это, вероятно, не совсем то, что вы хотели.
источник