Как (временно) освободить память от VirtualAlloc?

Когда используешь VirtualAlloc Я могу (ab) использовать следующее свойство для упрощения управления памятью.

Фактические физические страницы не распределяются, если / пока виртуальный адрес фактически не доступен.

Я запускаю следующий код для выделения блока.

type
  PArrayMem = ^TArrayMem;    //pointer
  TArrayMem = packed record  //as per documentation
    RefCount: Integer;
    Length: NativeInt;
    Elements: Integer;
  end;

var
  a: array of integer;  //dynamic array, structure see above

procedure TForm38.Button1Click(Sender: TObject);
const
  AllocSize = 1024 * 1024 * 1024; //1 GB
var
  ArrayMem: PArrayMem;
begin
  //SetLength(a, 1024*1024*1024); //1G x 8*16
  ArrayMem:= VirtualAlloc(nil, AllocSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  ArrayMem.RefCount:= 1;
  ArrayMem.Length:= AllocSize div SizeOf(Integer);
  a:= @ArrayMem.Elements;   //a:= AddressOf(elements)
  a[1]:= 10;        //testing, works
  a[0]:= 4;
  a[500000]:= 56;   //Works, autocommits, only adds a few k to the used memory
  button1.Caption:= IntToStr(a[500000]);  //displays '56'
end;

Все это прекрасно работает. Если моя структура увеличивается до 1.000.000 элементов, все работает.
Однако предположим, что впоследствии моя структура сократилась до 1.000 элементов.

Как освободить ОЗУ, чтобы оно автоматически автоматически фиксировалось при необходимости?

ПРЕДУПРЕЖДЕНИЕ
Дэвид предупредил, что выделение больших (огромных) непрерывных страниц памяти сопряжено с большими затратами.
Поэтому может быть более выгодно разделить массив на более мелкие блоки и абстрагировать внутренние компоненты с помощью класса / записи.

1 ответ

Решение

Вы можете удалить страницы, используя VirtualFree прохождение MEM_DECOMMIT флаг. Затем вы можете зафиксировать снова, используя VirtualAlloc,

Или вы можете использовать DiscardVirtualMemory функция введена в Windows 8.1.

Используйте эту функцию для удаления содержимого памяти, которое больше не требуется, при сохранении самой области памяти. Сброс памяти может вернуть физическую оперативную память системе. Когда приложение снова обращается к области памяти, резервное ОЗУ восстанавливается, и содержимое памяти не определено.

Вы можете найти что-то полезное в комментариях к этому связанному вопросу: Новые API-интерфейсы Windows 8.1 для управления виртуальной памятью: `DiscardVirtualMemory()` vs `VirtualAlloc()` и `MEM_RESET` и`MEM_RESET_UNDO`

Другие вопросы по тегам