В блоге VMware vSphere появилась интересная запись о том, как происходит работа с памятью в гипервизоре VMware ESXi. Приведем ее основные моменты ниже.
Работа виртуальной машины и ее приложений с памятью (RAM) идет через виртуальную память (Virtual Memory), которая транслируется в физическую память сервера (Physical Memory). Память разбита на страницы - это такие блоки, которыми виртуальная память отображается на физическую. Размер этого блока у разных систем бывает разный, но для ESXi стандартный размер страниц равен 4 КБ, а больших страниц - 2 МБ.
Для трансляции виртуальных адресов в физические используется таблица страниц (Page Table), содержащая записи PTE (Page Table Entries):
Записи PTE хранят в себе ссылки на реальные физические адреса и некоторые параметры страницы памяти (подробнее можно почитать здесь). Структуры записей PTE могут быть разного размера - это WORD (16 bits/2 bytes), DWORD (32 bits/4 bytes) и QWORD (64 bits/8 bytes). Они адресуют большие блоки адресов в физической памяти, к примеру, DWORD адресует блок адресов 4 килобайта (например, адреса от 4096 до 8191).
Память читается и передается гостевой системе и приложениям страницами по 4 КБ или 2 МБ - это позволяет читать содержимое ячеек памяти блоками, что существенно ускоряет быстродействие. Естественно, что при таком подходе есть фрагментация памяти - редко когда требуется записать целое число страниц, и часть памяти остается неиспользуемой. При увеличении размера страницы растет и их фрагментация, но увеличивается быстродействие.
Таблицы страниц (а их может быть несколько) управляются программным или аппаратным компонентом Memory Management Unit (MMU). В случае аппаратного MMU гипервизор передает функции по управлению трансляцией ему, а программный MMU реализован на уровне VMM (Virtual Machine Monitor, часть гипервизора ESXi):
Важный компонент MMU - это буфер ассоциативной трансляции (Translation Lookaside Buffer, TLB), который представляет собой кэш для MMU. TLB всегда находится как минимум в физической памяти, а для процессоров он часто реализован на уровне самого CPU, чтобы обращение к нему было максимально быстрым. Поэтому обычно время доступа к TLB на процессоре составляет около 10 наносекунд, в то время, как доступ к физической памяти составляет примерно 100 наносекунд. VMware vSphere поддерживает Hardware MMU Offload, то есть передачу функций управления памятью на сторону MMU физического процессора.
Итак, если от виртуальной машины появился запрос на доступ к виртуальному адресу 0x00004105, то этот адрес разбивается на адрес виртуальной страницы (Virtual page number - 0x0004) и смещение (Offset - 0x105 - область внутри страницы, к которой идет обращение):
Смещение напрямую передается при доступе к физической странице памяти, а вот тэг виртуальной страницы ищется в TLB. В данном случае в TLB есть запись, что соответствующий этому тэгу адрес физической страницы это 0x0007, соответственно трансляция виртуальной страницы в физическую прошла успешно. Это называется TLB Hit, то есть попадание в кэш.
Возможна и другая ситуация - при декомпозиции виртуального адреса получаемый тэг 0x0003 отсутствует в TLB. В этом случае происходит поиск страницы в физической памяти по тэгу (страницу номер 3) и уже ее адрес транслируется (0x006). Далее запись с этим тэгом добавляется в TLB (при этом старые записи из кэша вытесняются, если он заполнен):
Надо отметить, что такая операция вызывает несколько большую задержку (так как приходится искать в глобальной памяти), и такая ситуация называется TLB Miss, то есть промах TLB.
Но это не самая плохая ситуация, так как счет latency все равно идет на наносекунды. Но доступ может быть и гораздо более долгий (миллисекунды и даже секунды) в том случае, если нужная гостевой ОС страница засвопировалась на диск.
Посмотрим на пример:
Виртуальная машина обратилась к виртуальному адресу 0x00000460, для которого есть тэг 0x0000. В физической памяти для этого тэга выделена страница 0, которая означает, что искать эту страницу нужно на диске, куда страница была сброшена ввиду недостатка физической оперативной памяти.
В этом случае страница восстанавливается с диска в оперативную память (вытесняя самую старую по времени обращения страницу), ну и далее происходит трансляция адреса к этой странице. Эта ситуация называется отказ страницы (Page Fault), что приводит к задержкам в операциях приложения, поэтому иногда полезно отслеживать Page Faults отдельных процессов, чтобы понимать причину падения быстродействия при работе с памятью.