Управление памятью в операционной системе WINDOWS, страница 14

Уплотнение кучи

По мере того как вы используете кучу, принадлежащая ей память становится все более фрагментированной. Это значит, что свободная память кучи разбита на множество небольших участков, перемежающихся с блоками памяти, которые используются вашей программой для хранения данных. Чтобы скомпоновать все свободное пространство кучи в один большой блок, необходимо выполнить уплотнение кучи при помощи вызова HeapCompact. Этому вызову следует передать дескриптор кучи. Кроме того, вы можете использовать флаг НЕАР_ NO_SERIALIZE.

Проверка корректности данных, расположенных в куче

В процессе работы программа может нарушить целостность кучи. Например, при последовательном доступе к элементам массива вы можете по ошибке зайти за его пределы и осуществить запись в память, которая этому массиву не принадлежит. Возможно, вы не обратите внимание на то, что некоторый блок памяти уже освобожден, и попытаетесь сохранить в нем данные. Чтобы проверить целостность кучи, можно использовать функцию HeapValidate. При помощи этой функции можно проверить целостность всей кучи (для этого следует указать в качестве адреса проверки значение 0) или отдельного блока памяти.

Функция HeapWalk позволяет последовательно перебрать блоки памяти, выделенные в куче. Эта функция возвращает информацию о каждом блоке в структуре PROCESS_HEAP_ENTRY (табл.3). Каждое обращение к функции возвращает ин формацию о следующем блоке до тех пор, пока вы не переберете все блоки. Если при этом вы намерены использовать HeapValidate для того, чтобы проверить целостность блока, информацию о котором удалось получить при помощи HeapWalk, имейте в виду, что исполнение HeapValidate в отношении блока, который не выделен, закончится неудачей. По этой причине функцию HeapValidate следует использовать в отношении только тех блоков, для которых установлен флаг PROCESS_ HEAP_ENTRY_BUSY.

Структура PROCESS_HEAP_ENTRYТаблица 3.

Поле

Тип

Описание

IpData

PVOID

Указатель на данные

cdData

DWORD

Размер блока

cbOverhead

BYTE

Количество байт, используемых для управления

блоком

iRegionIndex

BYTE

Индекс участка памяти

wFlags

WORD

Статус участка памяти

hMem

HANDLE

Дескриптор выделенного участка памяти

Region.dwCommittedSize

DWORD

Количество выделенных байт

Region.dwUnCommittedSize

DWORD

Количество невыделенных байт

RegionlpFirstBlock

LPVOID

Указатель на первый корректный блок памяти

Region.IpLastBlock

LPVOID

Указатель на первый некорректный блок памяти

Увеличение производительности программы с использованием нескольких куч

Используя несколько пулов свободной памяти вместо одного, можно улучшить производительность вашей программы. Очевидным способом повышения эффективности использования памяти является применение разных куч для хранения элементов и объектов разного размера. В этом случае удается избежать фрагментации памяти, так как при освобождении участка, использованного для хранения одного элемента, этот же участок можно использовал для хранения другого элемента того же самого размера.

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