如何锁定一个地址空间块在物理内存中,不允许页面交换出去,放到虚拟内存中?
下面是一个简单的例子:
如果不点击 Btn2,那么一旦最小化程序,就会发现程序的物理内存占用大大减小,只有2M左右,其余的内存都被交换(swap)到虚拟内存中去了,这样如果你的程序要继续访问pos_array的话,就会导致Page Fault(可用Process Explorer去查看进程的内存相关的性能参数),即内存页面访问失败,需要从虚拟内存中重新交换到物理内存,从而导致性能降低。
点击Btn2之后,pos_array这72MB的内存就永久锁定在物理内存了,即使最小化也不会被交换出去,可以用Process Explorer看到,不论点击Btn1多少次,Page Fault几乎不增加的。而没有Btn2的话,只要最小化,再次点击Btn1就会导致大量的Page Fault!
var
pos_array: array[1..30, 1..640*480] of TPoint; // 共约72MB内存!如果不VirtualLock,一旦最小化程序,就会导致内存被交换出去到虚拟内存中。
procedure TForm1.Btn1Click(Sender: TObject);
var
i : Integer;
j : Integer;
begin
for i := 1 to 30 do
for j := 1 to 640 * 480 do
begin
pos_array[i][j].X := Random(640);
pos_array[i][i].Y := Random(480);
end;
end;
procedure TForm1.btn2Click(Sender: TObject);
var
pid : Thandle;
process: THandle;
begin
pid := GetCurrentProcessId;
process := OpenProcess(PROCESS_SET_QUOTA, FALSE, pid);
if not SetProcessWorkingSetSize(Process, 400*1000*1000, 400*1000*1000) then Beep;
VirtualLock(@pos_array[1][1], SizeOf(pos_array));
Caption := SysErrorMessage(GetLastError);
end;