17.1.23

Обзор Virtual Address Space - VAS

По материалам статьи Slava Oks: A look at Virtual Address Space - VAS


Память представляет собой набор разделяемых между приложениями, их компонентами и операционной системой ресурсов. Нужно чётко себе представлять, что происходит при обращении к каждому конкретному ресурсу памяти. Очень часто, разработчики, пользователи или администраторы баз данных ошибочно считают, что при обращении к разным ресурсам памяти используется один универсальный раздел памяти. Такое представление было справедливым для DOS, когда всё было просто и не существовало даже понятия виртуальной памяти, а приложения не разделяли ресурсы компьютера между собой. С тех пор многое изменились.

Ресурсы памяти бывают нескольких типов. Ресурсы могут управляться операционной системой или пользовательским кодом, поэтому для разработчиков очень важно получить полное представление об этих ресурсах.
Как и обещал автор, в этой статье он хотел бы поговорить о виртуальном адресном пространстве памяти - Virtual Address Space (VAS). В его предыдущей статье было показано, как можно будет контролировать VAS в следующей версии SQL Server 2005. VAS - это такой ресурс, которому при разрешении проблем памяти очень часто не уделяют должного внимания. Также, этой темой часто пренебрегают и в книгах, при описании менеджера памяти. Даже в Task Manager Windows нет счётчиков производительности для использования процессами VAS. Но понимание того, как процессы в Windows работают с VAS, является очень критичным при исследовании проблем памяти.
Каждый процесс имеет собственное VAS. Windows выделяет отдельную область VAS для нового процесса, когда вызывается CreateProcess API. К тому же, разработчикам предоставляется возможность распределять/высвобождать участки VAS, используя интерфейсы VirtualAlloc/VirtualFree API. Участок VAS может быть закреплён за физической памятью немедленно или в тот момент, когда это необходимо. Если нужно закрепить участок VAS немедленно, операционная система сначала ассигнует участок VAS, и только потом предоставит к нему доступ. Минимальный размер такого распределяемого участка равен 64 КБ (Это нужно запомнить, т.к. это очень важно!) и, кроме того, все участки VAS являются кратными 64 КБ. В свою очередь привязка VAS к физической памяти основа на базовом размере страницы, который может равняться 4 КБ или 8 КБ (у платформ x86 и IA64 существуют также большие страницы 4 МБ и 16 МБ, но мы поговорим о них как-нибудь в другой раз). Нужно отметить очень важный момент: любое новое ассигнование через VirtualAlloc всегда будет округлятся до 64 КБ, причём, если потом будет распределятся новый участок VAS, связанный с физической памятью, операционная система будет выбирать округлённые до размера страницы куски физической памяти, и они будут выбираться из VAS процесса, которое было округлено до 64 КБ (автор признаётся, что когда первый раз узнал об этом, он был в шоке!). Например, если интерфейс VirtualAlloc вызывается с флагом COMMIT для ассигнования 1024 байт, операционная система распределит для указанного процесса участок VAS в 64 КБ и ассигнует в его распоряжение страницу в 4 или 8 КБ физической памяти. Подытоживая это можно сказать, что нужно быть очень осторожным при использовании интерфейса VirtualAlloc API. Даже если Вы его не используете, всё равно нужно хорошо понимать его значения в процедурах отладки, когда исследуется работа процесса с недостатком или вне VAS, поскольку этот механизм часто используется на платформе x86. Чтобы успешно разрешать подобные проблемы нужно понимать, чем является VAS и как его можно использовать.
В действительности, вполне возможно исчерпать VAS даже на платформе 64bit. В своей испытательной лаборатории, работая с большими блоками памяти, разработчики действительно несколько раз наблюдали исчерпание VAS, и также автор исследовал заявленный баг, в котором описывалась подобная проблема, но с блоками меньшего размера. Ключом к разрешению подобных проблем является то, что при проектировании приложения нужно следить за тем, что структуры данных должны масштабироваться с учётом установленного для блока количества физической памяти.
Как было сказано, процессу выдаются участки VAS. Всё, что распределяется, загружается, создаётся и отображается процессом, использует VAS таким образом, как это было указано выше при описании механизма использования запросов VirtualAlloc и предшествует дальнейшим действиям. Например, загрузчик, перед загрузкой библиотеки (dll) в VAS процесса, вызывает VirtualAlloc того типа, который распределяет участок VAS для dll; а при создании в процессе потока, операционная система в начале резервирует участок VAS для стека потока, и то же самое происходит при отображении файла в пространстве процесса.
Компоненты, когда они используют ассигнование участков VAS, должны использовать свой тип запросов VirtualAlloc. Операционная система на низком уровне распределяет виртуальный адресный дескриптор - virtual address descriptor (VAD), который представляет из себя объект - описатель виртуальной адресации, т.е. структуру, которая описывает участок VAS. Объект VAD полностью описывает участок VAS, его размер, атрибуты ассигнования и защиты. Как Вы могли догадаться, операционная система поддерживает древовидную структуру VAD. Дерево VAD предоставляет возможность операционной системе эффективно управлять VAS. Дерево VAD процесса можно увидеть, используя локальный отладчик ядра windbg. Кроме того, как Вы думаете, что делает интерфейс VirtualQuery API? Совершенно верно, с его помощью можно пройти по дереву VAD процесса, и именно его разработчики используют в SQL Server 2005 при генерации представления sys.dm_os_virtual_address_dump. Как Вы видите, Windows управляет VAS процесса так же, как управляется динамическая память (хип) любого типа с минимальным размером блока в 64 КБ. На практике можно написать собственный интерфейс, но, к сожалению, пока не предусмотрена возможность его подключения.
Автор подчёркивает, что VAS - это очень важный ресурс, который используется множеством различных компонент, загруженных в пространство процесса, поэтому очень важно иметь возможность отслеживать его состояние. Традиционно, для подобных целей используются счётчики производительности, с помощью которых хотелось бы отслеживать, сколько VAS в момент измерения используется процессом. Увы, Task Manager не имеет подобных счетчиков.
К сожалению, в Windows нет простого пути для определения того, что твориться в VAS. Но то, что операционная система не предоставляет такого механизма, не подразумевает того, что такой механизм не может быть создан. Есть несколько инструментов, которые можно использовать для исследования VAS. Один из них - vadump.exe. Автор доверяет информации, которую предоставляет VADUMP при обходе дерева VAD процесса, для чего используется VirtualQuery API. Эта информация об участках VAS, которую можно анализировать.
Но, не смотря на то, что VADUMP предоставляет достаточно много информации, очень часто её может оказаться недостаточно для выявления проблемы с VAS, то есть её утечки. Для многих участков VAS, VADUMP не снабжает разработчика информацией о том, какому компоненту этот участок принадлежит. Одним из способов получения такой информации состоит в использовании вызовов VirtualAlloc/VirtualFree и последующего отслеживания всех операций с VAS. Именно это делает ещё один инструмент - LeakDiag, который построен на специальной библиотеке, разработанной Microsoft Research, с помощью которой обходится дерево VAD и для этого применяется интерфейсы VAS API. Для каждого ассигнования, LeakDiag запоминает информацию о распределении и о стеке. В любой момент эта информация может быть выгружена в файл для анализа. Насколько автор осведомлён, LeakDiag является в настоящее время единственным инструментом, с помощью которого можно исследовать VAS на таком уровне. Скачать LeakDiag можно по этой ссылке:

ftp://ftp.microsoft.com/PSS/Tools/Developer Support Tools/LeakDiag/

В качестве резюме, автор хотел бы перечислить некоторые важные моменты, которые он хотел подчеркнуть в этой статье:

  • VAS часто пренебрегают.

  • VAS - ограниченный ресурс даже для 64bit платформ.

  • Windows управляет VAS также, как и любой динамической памятью.

  • Минимальный участок VAS - 64 КБ.

  • Утечка VAS может привести к завершению процесса (Например, когда чересчур используется DBCC PINTABLE).

  • Для контроля VAS пока ещё существует не много инструментов.

Автор надеется, что эти моменты будут учитываться читателями. Понимание того, как работает VAS - это первый шаг к пониманию работы Менеджера Памяти SQL Server. В следующей статье автор продолжит рассказ о других типах ресурсов памяти, а также опишет различные типы вытеснения памяти.

Комментариев нет:

Отправить комментарий