Delphi SetProcessWorkingSetSize-什么';什么是陷阱?

Delphi SetProcessWorkingSetSize-什么';什么是陷阱?,delphi,memory-management,Delphi,Memory Management,我找到了一个 代码如下: procedure TrimAppMemorySize; var MainHandle : THandle; begin try MainHandle := OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessID) ; SetProcessWorkingSetSize(MainHandle, $FFFFFFFF, $FFFFFFFF) ; CloseHandle(MainHan

我找到了一个

代码如下:

procedure TrimAppMemorySize;
var
  MainHandle : THandle;
begin
  try
    MainHandle := OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessID) ;
    SetProcessWorkingSetSize(MainHandle, $FFFFFFFF, $FFFFFFFF) ;
    CloseHandle(MainHandle) ;
    Log('Trimmed Memory Successfull!');
  except
    Log('Failed to trim Memory!');
  end;
  Application.ProcessMessages;
end;
我试过了,效果很好——即使我的应用程序正在做一些事情,我启动了按钮按钮等等,它仍然能做它的事情,而且它的效果就像一个符咒。我在资源监视器中查看我的应用程序内存使用情况,就我所见,一切都很好

所以。。有什么问题吗?我们都会处理内存问题,但解决方案真的那么简单吗?谁能告诉我每60秒做一次是不是件坏事

我将重新启动并尝试运行我的程序,然后发布我的资源监视器的屏幕截图。

问题是,您刚刚告诉操作系统从您的工作集中删除内存中的页面。假设操作系统正在删除没有数据的页面,您将无法再次访问这些页面,那么就没有问题了。但是,如果它正在调出您的进程将来需要的数据,那么您只需告诉Windows“请多调出页面错误”


这段代码的主要问题是,为了系统的其余部分,您实际上牺牲了自己进程的性能(尽管颠簸实际上会损害整个系统)。这有点高尚,但显然不是“免费捕获”。

是的,这是一件坏事。你告诉操作系统你比它更了解内存管理,这可能不是真的。您要将所有非活动内存分页到磁盘。它服从。当你再次触摸任何一个内存时,操作系统必须将其分页回RAM。您正在强制执行实际上不知道需要的磁盘I/O

如果操作系统需要更多的空闲内存,它可以找出哪些内存最近没有被使用,并将其分页。这可能来自您的程序,也可能来自其他程序。但是,如果操作系统不需要更多的空闲RAM,那么您只需要强制执行一些无人要求的磁盘I/O

如果你有你知道你不再需要的记忆,释放它。不要只是将其分页到磁盘。如果你有操作系统认为你不需要的内存,它会根据需要自动为你分页


另外,调用
Application.ProcessMessages
通常是不明智的,除非您知道主线程需要处理一些它自己无法处理的消息。当无事可做时,应用程序会自动处理消息,因此,如果您无事可做,只需让应用程序自行运行。

这在道德上等同于向操作系统假装您的机器处于RAM危机的永久状态。系统比你更清楚如何管理它的内存,让它继续工作吧


不幸的是,当他们的系统使用所有的RAM和CPU时,人们担心这是一个非常常见的错误。事实上,如果你的系统没有充分利用它的资源,你应该担心

实际上,当使用GlobalAlloc/GlobalFree Windows时,确实倾向于将这些内存块连接到您的进程,我让进程“看起来”使用了400MB内存,而它只使用了40MB,因为GlobalFree并没有真正释放回内存(我们讨论的是在后台运行的实时进程,只要机器还在运行)。在这种情况下,我发现告诉Windows压缩进程内存的功能非常有用。我确实使用GetProcessMemoryInfo并检查当前的.WorkingSetSize,如果大于某个数量(如100MB)内存被压缩。是的,这确实会导致正在使用的内存出现页面错误,但内存被释放回内核供其他进程使用


因此,在某些情况下,我发现Windows在“垃圾收集”和返回资源方面做得不好。很高兴这个调用可用,它非常有用。

谢谢-所以根本不用它,明白了。:)你可以调用GetCurrentProcess而不是OpenProcess。它为您提供了一个句柄,您的进程在大多数情况下都可以使用该句柄来引用自身,并且您不需要为权限或关闭它而烦恼。如果您正在查找内存问题并认为这是一个解决方案,那么您看到的任务管理器列是错误的。不要查看Mem使用/工作集。这只会告诉您内存的当前部分在RAM中。查看VM大小/提交大小。这将告诉您进程使用的内存以及RAM和页面文件的计数。实际上
EmptyWorkingSet(GetCurrentProcess)执行与
SetProcessWorkingSetSize完全相同的操作(GetCurrentProcess,$FFFFFFFF,$FFFFFFFF)但正如这里所解释的;如果你没有严肃的理由,就不要使用它。如果它没有坏,就不要修理它。除非您在应用程序中遇到与内存相关的问题,否则我不会太担心自己处理它。如前所述,Windows可以为您解决这一问题,您需要担心的是从内存中释放/释放对象。