Поддерживает ли FastMM резервирование виртуальной памяти и обращение к частям для увеличения массива? - PullRequest
1 голос
/ 17 июня 2011

Я знаю, что могу зарезервировать виртуальную память, используя VirtualAlloc.
например Я могу потребовать 1 ГБ виртуальной памяти, а затем вызвать первые 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 Ответ

3 голосов
/ 17 июня 2011

Нет, FastMM4 (в последней версии, на которую я смотрел) явно не поддерживает это. Это действительно не та функциональность, которую вы ожидаете в диспетчере памяти общего назначения, поскольку ее довольно просто делать с вызовами VirtualAlloc.

NexusMM4 (который является частью NexusDB) делает то, что дает аналогичный результат, но не тратит все адресное пространство до того, как оно понадобится в фоновом режиме.

Если вы делаете начальное большое выделение (напрямую через GetMem или косвенно через динамический массив или тому подобное), то память выделяется только необходимого размера через VirtualAlloc.

Но если это распределение затем изменится до большего размера, NexusMM будет использовать другой способ выделения памяти, который позволит ему просто отобразить выделение из адресного пространства и переназначить его снова, с большим размером, когда дальнейшие перераспределения потребуют место.

Это предотвращает две основные проблемы, которые возникают у большинства диспетчеров памяти общего назначения при перераспределении:

  • во время обычного перераспределения существующее и новое распределение должны присутствовать в адресном пространстве одновременно, временно удваивая адресное пространство и требования к физической памяти
  • во время обычного перераспределения необходимо скопировать все содержимое существующего выделения

Таким образом, с NexusMM вы получите все преимущества того, что вы показали в своем псевдокоде (за исключением того, что первый realloc будет включать в себя копию, и что увеличение массива может изменить его адрес), просто используя обычный GetMem / ReallocMem / FreeMem звонки.

...