Как стать автором
Обновить

Продолжаем говорить о памяти – Page Sharing

Время на прочтение8 мин
Количество просмотров9K
image
Данная статья является второй из моего цикла статей, посвященного работе с памятью в среде виртуализации в целом, и технологии динамической памяти Hyper-V, которая появится появившейся в Windows Server 2008 R2 SP1 в частности.
Первая часть: habrahabr.ru/blogs/virtualization/93241
Здесь речь пойдет об одной из технологий «перевыделения памяти» под названием Page Sharing.

Как это работает?


Page Sharing – это одна из технологий динамического выделения памяти в гипервизорах, позволяющая выделять виртуальным машинам больше памяти, чем имеется физически – то есть то, что по-английски именуется «memory overcommitment».

Принцип работы этой технологии схож с некоторыми алгоритмами сжатия данных. Начинается все с того, что гипервизор «перелопачивает» все страницы памяти, имеющейся в системе, и вычисляет контрольные суммы (хэши) каждой страницы. Полученные значения заносятся в специальную таблицу. Затем гипервизор ищет в таблице одинаковые значения контрольных сумм, и при обнаружении совпадений производит побитовое сравнение соответствующих страниц. Если обнаруживаются полностью идентичные страницы — то из них остается только одна копия, и впоследствии виртуальные машины при обращении автоматически перенаправляются на нее. Так происходит ровно до тех пор, пока какая-то из виртуальных машин не захочет внести изменения в «расшаренную» страницу. Тогда создается отдельная копия этой страницы, и она уже не «расшаривается», а используется только одной виртуальной машиной. К сожалению, само «перелопачивание» памяти и вычисления хэшей, с дальнейшим поиском совпадений по таблице с побитовым сравнением – сам по себе процесс достаточно ресурсоемкий и долгий, по длительности может занимать вплоть до нескольких часов при больших объемах памяти.

Page Sharing, TLB, Large Memory Pages и все-все-все

Для начала давайте посмотрим на общие принципы работы с памятью, что такое большие страницы памяти (Large Memory Pages, далее – LMP), для чего нужен кэш ассоциативной трансляции (Translation Lookaside Buffer, далее – TLB) и причем тут, собственно, все это и Page Sharing. Вот что пишет в своей статье Алан Зейчик (Alan Zeichick), инженер из компании AMD (хотя в статье говориться о работу с памятью виртуальной машины Java, это в принципе применимо и к виртуализации компьютеров. Я приведу частичный перевод статьи, оригинал на английском языке находится тут):
Все х86-совместимые процессоры, и все современные 32- и 64-разрядные ОС используют страничную организацию физической и виртуальной памяти. Для каждого приложения производится сопоставление виртуального адреса страницы и физического адреса посредством таблицы страниц. Чтобы ускорить этот процесс сопоставления, современные процессоры используют буфер ассоциативной трансляции (translation lookaside buffer, TLB), который кэширует сопоставления физических и виртуальных адресов, к которым обращались наиболее недавно.
Как правило, область памяти, выделяемая приложению, не является непрерывной, и страницы памяти часто бывают фрагментированы. Но из-за того, что таблица страниц памяти скрывает физические адреса от приложений, приложения «думают», что предоставленная им область памяти является непрерывной. По аналогии – приложения, не работающие с файловой системой напрямую, не имеют понятия о фрагментации отдельных файлов.
Когда запущенное приложение осуществляет доступ к памяти, процессор использует таблицу страниц для преобразования виртуального адреса, используемого приложением, в физический адрес. Как уже было сказано выше, для ускорения этого процесса используется кэширующая система – буфер ассоциативной трансляции. Если запрошенный адрес находится в TLB – процессор может обработать запрос намного быстрее из-за отсутствия необходимости поиска соответствия по всей таблице страниц. Соответственно, если запрошенный адрес в кэше TLB отсутствует – то производится стандартная операция поиска соответствия виртуального и физического адресов в таблице страниц, и лишь после этого запрос может быть обработан.
Из-за огромного количества страниц, эффективность работы кэша TLB имеет огромную важность. В стандартном 32-битном сервере под управлением любой ОС – не важно, Windows это, Linux, или какой-то другой Unix, с 4 Гб RAM, таблица страниц будет содержать миллион записей о каждой 4-килобайтной странице. А теперь представьте, если у нас, к примеру, 64-битная ОС и, скажем, 32 Гб памяти? Получается аж 8 млн. 4-килобайтовых страниц.

И далее:
Почему использование этой технологии [больших страниц] удобнее? Допустим, наше приложение пытается прочитать 1 Мбайт (1024 Кбайт) непрерывных данных, доступ к которым осуществлялся сравнительно давно (то есть в кэше TLB этот запрос не сохранился). Если страницы памяти имеют размер 4 Кбайт – то это означает, что придется осуществить доступ к 256 страницам. Получается, что нам придется произвести 256 операций поиска в таблице страниц, в которой могут быть миллионы записей. Это займет достаточно много времени.
Теперь представим, что размер страницы равен 2 Мбайт (2048 Кбайт). В этом случае поиск в таблице страниц придется осуществлять единожды, если блок данных в 1 Мбайт, который нам нужен, находится целиком в одной странице, или же дважды – в противном случае. А если еще используется TLB – то процесс протекает еще намного быстрее.
Для маленьких страниц, TLB содержит 32 записи для кэша L1 и 512 записей для кэша L2. Поскольку каждая запись соответствует 4-килобайтной странице, получается, что весь TLB покрывает всего 2 Мбайт виртуальной памяти.
Для больших страниц, буфер TLB содержит 8 записей. Поскольку каждая запись здесь адресует 2 Мбайт памяти, TLB адресуют 16 Мбайт виртуальной памяти. Этот механизм становится намного более эффективным при использовании приложений, требовательных к объему памяти. Представьте, что ваше приложение пытается прочитать, допустим, 2 Гбайт данных. Что будет быстрее — считывание тысячи закэшированных 2-мегабайтных страниц или «перелопачивание» полумиллиона маленьких 4-килобайтных страниц?


Путем нехитрых арифметических действий можно подсчитать количество записей в таблице страниц при различных объемах памяти. Если принять размер страницы в 4 килобайта, то для 4 Гб памяти их будет всего 1 миллион. Для 32 Гб – уже 8 миллионов, для 64 Гб – 16 млн. записей, и аж целых 256 миллионов записей для 1 Тб памяти. А теперь вспомним, что сервера уже давно поддерживают не то, что 32 или 64, а даже 192 Гб памяти (к примеру – HP DL385 G6), а недавно вышедший процессор Intel Nehalem EX по спецификации поддерживает до 256 Гб памяти на один процессорный сокет. Получается, что терабайт памяти – это уже не из области фантастики. Это всего лишь один четырехпроцессорный сервер. Если использовать старую модель организации памяти в виде 4-килобайтных страниц – получим 256 миллионов страниц, и работа с такими объемами памяти будет напоминать вычерпывание плавательного бассейна пивной кружкой. Так что использование больших страниц памяти – это не отдаленное будущее, а самое что ни на есть настоящее.
Подводя резюме: кэш ассоциативной трансляции – это достаточно важный системный ресурс, эффективность использования которого сильно влияет на производительность системы. Стандартом де-факто в 32-битных системах, поддерживающих максимум 4 Гб, памяти была организация памяти в виде страниц длиной 4 Кб. В настоящее время, когда все больше и больше используются 64-битные системы, а объемы памяти могут исчисляться десятками и сотнями гигабайт – использование такой организации памяти может серьезно снизить эффективность использования TLB и, следовательно – производительность системы в целом.
Нельзя так же не упомянуть про новую технологию, именуемую «преобразование адресов второго уровня» (Second Level Address Translation, SLAT). Эта технология именуется по-разному у разных вендоров (у AMD – Rapid Virtualization Indexing (RVI) или Nested Page Tables (NPT), у Intel – Extended Page Tables (EPT)). Она позволяет напрямую преобразовывать гостевые адреса (то есть внутри виртуальной машины) в физические адреса. Такое преобразование позволяет серьезно повысить производительность (официально подтвержден прирост в 20%, некоторые говорят о 100%-м росте производительности) по сравнению с системами, где эта фича не поддерживается. Так что для виртуализации SLAT – это полезно, и является одним из поводов для перехода на железо и софт, поддерживающие его.
Тем не менее, многие забывают, или просто не знают, что SLAT разрабатывали и оптимизировали для работы с большими страницами памяти. Если же поддержка больших страниц не включена – то кэш TLB работает менее эффективно, а использование SLAT с маленькими страницами может привести наоборот к 20%-му падению производительности. Кроме этого, мы не получим 10-20%-го роста производительности от самого использования больших страниц, и, соответственно – в общем и целом потеряем до 40% производительности.
Суммируя вышесказанное мы видим, что Large Memory Pages – очень важный фактор, способный дать прирост производительности до 40%, и вопрос, использовать ли их – является риторическим. Large Memory Pages является продуктом эволюции компьютерных систем, точно так же, как и 64-битная архитектура процессоров, или же jumbo frames в сетевых технологиях.

Казалось бы, причем тут Ю. Лужков?

У многих при прочтении статьи возникнет вполне резонный вопрос: а зачем я тут растекался мысью по древу, рассказывая про всякие Большие Страницы и КЭШи ассоциативной трансляции? Ведь статья была изначально про Page Sharing? Ответ очень прост: Page Sharing практически не работает при использовании больших страниц. Почему? Элементарно, Ватсон: из-за большого объема страниц (2048 Кб против 2 Кб) вероятность нахождения в памяти полностью идентичных страниц снижается практически до нуля. Это – один из немногих случаев, когда Microsoft и VMware полностью солидарны во мнении:
communities.vmware.com/message/1262016#1262016
Единственная проблема при использовании больших страниц заключается в том, что для работы Page Sharing необходимо найти полностью идентичные страницы памяти размером в 2 Мбайт (в сравнении с более мелкими 4-килобайтовыми страницами). Вероятность этого намного ниже (кроме пустых страниц в гостевой ОС, забитых целиком «нулями)), а ESX не пытается разделять большие страницы памяти и именно поэтому экономия памяти за счет использования TPS снижается, когда гипервизор сопоставляет все гостевые страницы с физическими большими страницами.

Говоря кратко — Page Sharing эффективно работает с 4-килобайтными страницами, но при использовании больших, 2-мегабайтных страниц не дает ровным счетом никаких преимуществ.

Пустые страницы

Как ни странно, но эффективнее всего Page Sharing работает при больших объемах неиспользуемой памяти – то есть когда имеется много страниц, забитых нулями. Они полностью идентичны, и «расшариваются» проще всего. Ну примерно как сжатие «квадрата Малевича» в формате bmp. Проблема в том, что некоторые ОС (в частности, Windows 7) стремятся использовать весь доступный объем памяти, и это не баг, а фича – в частности, SuperFetch в Windows Vista/7, о которой я писал ранее. Так вот, это тоже будет приводить к снижению эффективности технологии Page Sharing.

Резюме


  • Большие (2 Мбайт) страницы памяти (Large Memory Pages) поддерживаются в процессорах уже сейчас. AMD поддерживает большие страницы памяти в нескольких последних поколениях процессоров Opteron, Intel же внедрила их поддержку в новых процессорах «Nehalem». То есть, очень скоро это станет общепринятым стандартом.
    — Page Sharing работает на системах с большими страницами памяти практически с нулевой эффективностью. Если 4-килобайтные страницы достаточно часто могут быть идентичны между собой, то при размере страницы в 2 Мбайт найти полностью одинаковые страницы практически невозможно. Еще раз – это один из немногих моментов, где мнения Microsoft и VMware совпадают.
    — Итак, page sharing эффективно работает только с 4-килобайтовыми страницами. Но при использовании 4-килобайтных страниц падает эффективность работы TLB и невозможно использовать SLAT, что приводит к падению производительности системы до 40%.
    — В Windows Server 2008/2008 R2, а так же в Windows Vista/7 поддержка больших страниц памяти включена по умолчанию.
    — Большие страницы поддерживается в Hyper-V R2 на уровне гипервизора.
  • Если даже забыть про большие страницы памяти – эффективность page sharing снижается из-за того, что современные ОС пытаются использовать весь имеющийся в наличии объем памяти (SuperFetch).
  • Процесс подготовки к работе Page Sharing включает в себя хэширование всех страниц памяти, сохранение хэшей в таблицу и затем – побитовое сравнение. Этот процесс долог и ресурсоемок, и может занять часы.
  • Page Sharing – это не самый эффективный метод динамического распределения памяти. То есть, если необходимо срочно добавить памяти какой-либо виртуальной машине, или же если у одной виртуальной машины освободилась память и ее нужно дать другой виртуалке – page sharing не сильно поможет.

Из этого всего выходит, что технология Page Sharing при использовании современного оборудования и операционных систем становится в лучшем случае бесполезной, а то и вредной – снижая производительность и не позволяя использовать новые возможности железа и ОС.

В следующей статье мы продолжем разговор о технологиях «memory overcommitment», на этот раз речь пойдет о Second Level Paging.
Теги:
Хабы:
Всего голосов 56: ↑50 и ↓6+44
Комментарии35

Публикации

Истории

Работа

DevOps инженер
32 вакансии

Ближайшие события

2 – 18 декабря
Yandex DataLens Festival 2024
МоскваОнлайн
11 – 13 декабря
Международная конференция по AI/ML «AI Journey»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань