【发布时间】:2016-06-22 14:53:32
【问题描述】:
当使用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 个元素。
如何释放 RAM,以便在再次需要时自动提交?
警告
大卫警告我,分配一个提交的大(巨大)连续内存页面会带来很大的成本。
因此,将数组拆分为更小的块并使用类/记录抽象出内部可能更有利。
【问题讨论】:
-
你想释放什么不是很清楚,“内存”是一个非常模糊的术语。您是在谈论 RAM 还是地址空间? RAM 是自动的,无需帮助。如果您想释放地址空间,那么像这样使用 VirtualAlloc() 是个坏主意,请改用 HeapAlloc()。
-
@HansPassant,对不起,我的意思是 RAM。我不担心地址空间,因为我只在 Win64 中运行。
-
您不能直接修改 RAM 分配,这是操作系统的工作。 SetProcessWorkingSetSize() 是一个粗暴的大锤来强制 RAM 页面出来,在这里肯定不合适。跟进@David,我认为他不明白你的意思。
-
@HansPassant, ?
SetProcessWorkingSetSize来自哪里?我又在说VirtualAlloc+VirtualFree+VirtualAlloc了。 -
您正在发送混合信号,我跟进了您的“对不起,我的意思是 RAM”评论。不知道你在做什么了,我最好别插手了。
标签: winapi virtualalloc