Средства разработки приложений

         

Модуль AcedMemory


Этот модуль предназначен для замены стандартного менеджера памяти Borland Delphi альтернативным механизмом распределения памяти. Целью разработки нового менеджера памяти было стремление оптимизировать работу с небольшими блоками памяти, которые возникают при организации хранения данных в виде объектной базы, когда каждая запись представляется экземпляром соответствующего класса. Под оптимизацией подразумевается, во-первых, повышение скорости при выделении/освобождении блоков памяти, во-вторых, решение проблемы фрагментации свободных блоков. Рассмотрим подробнее, за счет чего это достигается при использовании AcedMemory.

Память запрашивается у операционной системы вызовом VirtualAlloc блоками размером 2МБ, которые в данном контексте называются регионами. Каждый регион состоит из 32 блоков размером 64кБ. Каждый такой блок предназначен для фрагментов памяти определенного размера. Например, один блок может содержать 4 фрагмента по 16кБ, другой – 1024 фрагмента по 64 байта и т.д. Когда из прикладной программы вызывается функция GetMem, размер выделяемых фрагментов памяти округляется вверх до ближайшего числа, равного 2 в степени N, где N может быть от 3 до 16. Когда все фрагменты памяти нужного размера в составе блока заняты, в регионе выделяется следующий блок под фрагменты памяти нужного размера. Если все 32 блока в составе региона заняты, создается новый регион размером 2МБ. Адрес каждого фрагмента памяти (до 64кБ) кратен его размеру, что положительно влияет на производительность. В отличие от стандартного менеджера памяти, размер выделяемых фрагментов не хранится в памяти с отрицательным смещением, а вычисляется, при необходимости, по адресу фрагмента. Когда требуется выделить фрагмент памяти размером более 64кБ, этот размер округляется вверх до числа, кратного 4096 байтам, а затем вызывается функция VirtualAlloc для запроса соответствующего блока памяти у операционной системы.

Для подключения AcedMemory к проекту, ссылку на этот модуль необходимо добавить в раздел uses файла проекта, причем AcedMemory должен стоять первым в этом разделе.
Стандартные модули Forms, Classes и прочие должны находиться в списке uses, после AcedMemory. Если этого не сделать, при завершении программы возникнет ошибка. Это происходит из-за того, что в разделе finalization модуля Classes косвенно вызывается функция FreeMem для освобождения некоторых блоков памяти, выделенных в процессе работы программы. Модули финализируются в порядке, обратном их перечислению в разделе uses файла проекта. Чтобы менеджер памяти AcedMemory был еще активен на момент вызова раздела finalization модуля Classes, ссылка на AcedMemory должна находиться в списке uses файла проекта перед модулем Classes и любыми другими модулями, использующим Classes, как, например, модуль Forms. Кроме, собственно, механизма для выделения/освобождения памяти, в модуле AcedMemory имеется несколько вспомогательных функций: G_GetMemSize возвращает размер блока памяти, адрес которого передан как параметр; функция G_GetTotalMemAllocated возвращает общий объем памяти, выделенный прикладной программе. Вызов этой функции не приводит к длительному пересчету размеров всех выделенных блоков. Вместо этого просто возвращается значение внутреннего счетчика памяти. Функция G_GetTotalMemCommitted возвращает общий размер физической памяти, выделенной программе операционной системой. Это число не учитывает память, выделенную в "куче" для служебных структур модуля AcedMemory, а также память, распределенную средствами, отличными от менеджера памяти.

Содержание раздела