Поддерживает ли FastMM резервирование виртуальной памяти и частичное обращение к массиву?
Я знаю, что могу зарезервировать виртуальную память, используя VirtualAlloc.
Например, я могу потребовать 1 ГБ виртуальной памяти, а затем вызвать первые МБ, чтобы разместить растущий массив.
Когда размер массива превышает 1 МБ, я вызываю 2-й МБ и так далее.
Таким образом, мне не нужно перемещать массив в памяти, когда он растет, он просто остается на месте, а менеджер виртуальной памяти Intel/AMD заботится о моих проблемах.
Однако FastMM поддерживает эту структуру, поэтому мне не нужно заниматься собственным управлением памятью?
Псевдокод:
type
PBigarray = ^TBigarray;
TBigArray = array[0..0] of SomeRecord;
....
begin
VirtualMem:= FastMM.ReserveVirtualMemory(1GB);
PBigArray:= FastMM.ClaimPhysicalMemory(VirtualMem, 1MB);
....
procedure GrowBigArray
begin
FastMM.ClaimMorePhysicalMemory(PBigArray, 1MB {extra});
//will generate OOM exception when claim exceeds 1GB
FastMM поддерживает это?
1 ответ
Нет, FastMM4 (по состоянию на последнюю версию, на которую я смотрел) явно не поддерживает это. Это действительно не та функциональность, которую вы ожидаете в диспетчере памяти общего назначения, так как это тривиально просто сделать с вызовами VirtualAlloc.
NexusMM4 (который является частью NexusDB) делает то, что дает вам аналогичный результат, но не тратит все адресное пространство до того, как оно понадобится в фоновом режиме.
Если вы делаете начальное большое выделение (напрямую через GetMem или косвенно через динамический массив или тому подобное), то память выделяется только необходимого размера через VirtualAlloc.
Но если это распределение затем изменится до большего размера, NexusMM будет использовать другой способ для выделения памяти, который позволяет ему просто отобразить распределение из адресного пространства и переназначить его снова, с большим размером, когда произойдет дальнейшее перераспределение.
Это предотвращает две основные проблемы, которые возникают у большинства диспетчеров памяти общего назначения при перераспределении:
- во время обычного перераспределения существующее и новое распределение должны присутствовать в адресном пространстве одновременно, временно удваивая адресное пространство и требования к физической памяти
- во время обычного перераспределения необходимо скопировать все содержимое существующего выделения
Таким образом, с NexusMM вы получите все преимущества того, что вы показали в своем псевдокоде (за исключением того, что первый realloc будет включать в себя копию, а увеличение массива может изменить его адрес), просто используя обычные вызовы GetMem/ReallocMem/FreeMem,