- PVSM.RU - https://www.pvsm.ru -
Привет! Меня зовут Роман Гущин. В Яндексе я занимаюсь ядром Linux. Некторое время назад я провел для системных администраторов семинар, посвященный общему описанию подсистемы управления памятью в Linux, а также некоторым проблемам, с которыми мы сталкивались, и методам их решения. Большая часть информации описывает «ванильное» ядро Linux (3.10), но некоторая часть специфична для ядра, использующегося в Яндексе. Вполне возможно, семинар окажется интересен не только системным администраторам, но и всем, кто хочет узнать, как в Linux устроена работа с памятью.
Основные темы, затронутые на семинаре:
Под катом вы найдете более подробный план доклада с раскрытием основных понятий и принципов.
Основная задача подсистемы — выделение физической памяти ядру и userspace-процессам, а также высвобождение и перераспределение в тех случаях, когда вся память занята.
Основные компоненты:
Схема NUMA [1] подразумевает, что к каждому физическому процессору присоединен некоторый объем памяти, к которому он может обращаться быстрее всего. Обращение к участкам памяти других процессоров происходит значительно медленнее.
Физическая память в ядре описывается тремя структурами: ноды (pg_data_t), зоны (struct zone), страницы (struct page). Виртуальная память у каждого процесса своя и описывается при помощи структуры struct mm_struct. Они, в свою очередь, делятся на регионы (struct vm_area_struct).
Ядро взаимодействует с подсистемой memory management при помощи таких функцций функций, как __get_free_page(), kmalloc(), kfree(), vmalloc(). Они отвечают за выделение свободных страниц, больших и малых участков памяти, а также их высвобождение. Существует целое семейство подобных функций, отличающихся небольшими особенностями, например, будет ли занулена область при высвобождении.
Пользовательские программы взаимодействуют с mm-подсистемой при помощи функций mmap(), munmap(), brk(), mlock(), munlock(). Также есть функции posix_fadvice() и madvice(), которые могут давать ядру «cоветы». Но учитывать их в своих эвристиках оно строго говоря не обязано.
Система всегда старается поддерживать некоторый объем свободной памяти (free pool). Таким образом, память выделяется гораздо быстрее, т.к. не приходится высвобождать ее в тот момент, когда она уже действительно нужна.
Те страницы в памяти, которые используются постоянно (системные библиотеки и т.п), называются working set. Вытеснение их из памяти приводит к замедлению работы всей системы. Общая скорость потребления памяти в системе называется memory pressure. Эта величина может очень сильно колебаться в зависимости от того, насколько загружена система.
Всю незанятую ядром память в системе можно поделить на две части: анонимная память и файловая. Отличаются они тем, что про первую мы точно знаем, что каждый ее кусок соответствует какому-либо файлу, и его можно туда сбросить.
LRU расшифровывается как list recently used. Это абстракция, которая предлагает выкидывать страницы, к которым мы дольше всего не обращались. Реализовать ее в Linux полноценно невозможно, т.к. все что нам известно — было ли когда-либо обращение к той или иной странице. Чтобы как-то отслеживать частоту обращений к страницам используются списки active, inactive и unevictable. В последнем находятся залоченные пользователем страницы, которые не будут выбрасываться из памяти ни при каких условиях.
Существуют четкие правила перемещения между списками inactive и active. Под воздействием memory pressure, страницы из неактивного списка могут быть либо выброшены из памяти, либо перейти в активный. Страницы из активного списка перемещаются в неактивный, если к ним давно не было обращений.
Утилита top демонстрирует статистику потребления памяти в системе. Програмка vmtouch — показывает какая часть определенного файла находится в памяти. Исчерпывающую информацию по количеству файловых, активных и неактивных страниц можно найти в /proc/vmstat. Статистика buddy allocator есть в /proc/buddyinfo, а статистика slub allocator, соответственно, в /proc/slabinfo. Часто бывает полезно посмотреть на perf top, где отлично видны все проблемы с фрагментацией.
Сигруппы зародились из желания выделить группу из нескольких процессов, объединить их логически и ограничить их суммарное потребление памяти определенным. При этом, если они достигнут своего лимита, память должна высвобождаться именно из выделенного им объема. В этом случае нужно освободить память, принадлежащую именно этой сигруппе (это называется target reclaim). Если в системе просто закончилась память и нужно пополнить free pool — это называется global reclaim. C точки зрения аккаунтинга каждая страница принадлежит только одной сигруппе: той, которая ее первой прочитала.
Compaction — это механизм дефрагментации физической памяти. Механизм этот был достаточно долго сломан, примерно с версии 3.3 до версии 3.7. Это проявлялось в том, что на некоторых машинах с мощным фрагментирующим моментом спустя две недели работы все процессоры были заняты исключительно compaction и никакого полезного действия не совершали.
Автор: yaklamm
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/66572
Ссылки в тексте:
[1] NUMA: http://ru.wikipedia.org/wiki/Non-Uniform_Memory_Access
[2] Источник: http://habrahabr.ru/post/231957/
Нажмите здесь для печати.