如何说服内存管理器释放未使用的内存

WeG*_*ars 5 delphi fastmm

在最近的帖子中(我的程序永远不会释放内存.为什么?)我表明在使用FastMM时,应用程序不会释放大量内存回系统.最近我创建了一个人工测试程序,以确保它不是一个内存的问题,它只出现在FastMM中.

在这个程序中,我创建并销毁一个对象(与前一篇文章中使用的对象相同)500次.

内存要求是("私人工作集"):

没有FastMM
在运行循环之前:1.2MB
运行循环后:2.1MB

使用FastMM(激进的调试模式)
在运行循环之前:2.1MB
运行循环后:25MB

使用FastMM(发布模式)
运行循环之前:1.8MB
运行循环后:3MB

如果我多次运行循环,则内存要求不会增加.这意味着重用未释放的内存,因此这不是内存泄漏(内存泄漏会增加内存占用,每次运行时会有几KB/MB).


我的问题是:

如何在FastMM中禁用此行为?它甚至可能吗?我知道,如果我在没有FastMM或FastMM Release Mode的情况下发布程序,它将"浪费"适量的RAM.但是,根据需要禁用此行为,将帮助我(我们?)识别内存泄漏.实际上在我的第一篇文章中(见链接),很多人都认为我有泄漏.由于这种行为,显然造成了混乱.不,很明显没有泄漏.只是内存管理器拒绝释放大量内存.

它会释放额外的内存吗?什么时候?什么引发了这个?程序员可以触发吗?例如,当我知道我已经完成了RAM密集型任务并且用户可能暂时不使用该程序(最小化它)时,我可以将RAM刷回系统吗?当用户打开我的程序的多个实例时会发生什么?他们不会争夺内存吗?

Mas*_*ler 11

你不应该把它视为"浪费"RAM,真的.将其视为"缓存"未使用的RAM.内存管理器正在抓住未使用的内存,而不是因为某种原因将其释放回操作系统,事实上你已经在问题中找到了这个原因.

你说你继续在循环中重新运行相同的操作.当你这样做时,它仍然有旧的可用内存,它可以立即分配它,而不必向Windows请求一大堆新的堆.这是将"Fast"置于"FastMM"中的技巧之一,如果它没有这样做,你会发现你的程序运行得慢得多.

您无需担心FastMM调试模式图.这只是用于调试,并且您不会发布针对FullDebugMode编译的程序.并且"不使用FastMM"和"使用FastMM发布模式"之间的差异大约为1 MB,这在现代硬件上可以忽略不计.对于只需1 MB的低成本,您可以获得巨大的性能提升.所以不要担心.


Rob*_*edy 9

使FastMM快速发展的部分原因在于它将分配一大块内存并从中分割出更小的均匀大小的内存.如果块的任何部分正在使用中,则它们都不能释放回操作系统.

欢迎您使用其他内存管理器.一种方法是将所有分配直接路由到VirtualAlloc.分配将被四舍五入以一次占用整个页面,因此如果您有大量小分配,您的程序可能会受到影响,但是当您打电话时VirtualFree,您可以确信内存肯定不再属于您的程序.

另一种选择是将所有内容路由到OS堆.使用HeapAlloc.您甚至可以为程序启用低碎片堆(默认情况下从Windows Vista开始),这将使操作系统采用类似于FastMM使用的策略,但它允许您使用一些调试和分析工具从Microsoft跟踪程序的内存使用情况.但请注意,在您拨打电话后HeapFree,某些指标可能仍会将内存显示为属于您的程序.

此外,工作集指的是当前在物理RAM中的内存.你观察到这个数字上升并不意味着你的程序已经分配了更多的内存.它可以简单地表示您的程序触及了之前已分配但尚未放入RAM的内存.在你的循环中,你触摸了那个内存,操作系统还没有决定将它重新登录到磁盘.


WeG*_*ars 2

解决了

正如 Barry Kelly 所建议的,内存将由 FastaMM 自动释放。为了确认这一点,我创建了第二个分配大量 RAM 的程序。一旦Windows耗尽RAM,我的程序内存利用率就恢复到原来的值。

问题解决了。谢谢,巴里。