我知道内存使用在Windows上是一个非常复杂的问题。
我正在尝试为大型应用程序编写一个UI控件,显示“使用的内存百分比”数字,以便向用户显示可能是时候清理某些内存,或者更有可能重新启动应用。
一个实现使用来自MEMORYSTATUSEX的ullAvailVirtual作为基础,然后使用HeapWalk()来遍历进程堆以寻找额外的可用内存。 HeapWalk()步骤是必需的,因为我们注意到在运行分配并由堆释放的内存一段时间之后,ullAvailVirtual号从未返回并报告。经过数小时的密集工作后,ullAvailVirtual号码将不再准确报告可用内存量。
然而,这种方法被证明并不理想,因为即使进程堆没有被破坏,HeapWalk()偶尔也会返回奇怪的错误。此外,由于这是一个UI控件,堆行走代码每5-10秒执行一次。我曾尝试联系微软,了解HeapWalk()失败的原因,通过MSDN升级案例,但除了“你可能不应该这样做”之外,从未得到过答案。
因此,作为第二个实现,我使用PROCESS_MEMORY_COUNTERS中的PagefileUsage作为基础。然后我使用VirtualQueryEx遍历虚拟地址空间,将所有不是MEM_FREE的区域相加,并返回GetMappedFileNameA()的值。我的想法是,PageFileUsage本质上是“私有字节”,所以如果我将该进程使用的DLL的总大小添加到该值,那么它将是我的进程使用的内存量的一个很好的近似值。
第二种方法似乎(sorta)工作,至少它不会像堆walker方法那样导致崩溃。但是,如果启用了这两种方法,则值不相同。所以其中一种方法是错误的。
那么,StackOverflow世界......你将如何实现这个?
请记住,重点是向用户表明它正在变得“危险”,他们应该释放内存或重新启动应用程序。也许'使用百分比'不是这个问题的最佳解决方案?什么是?我的另一个想法是基于颜色的系统(红色,黄色,绿色,我可以基于更多因素而不仅仅是一个数字)
答案 0 :(得分:1)
是的,Windows内存管理器经过优化,可以快速有效地满足内存请求,不优化,可以轻松测量使用的空间。第一个缺点是发布的堆块很少被取消映射。它们只是标记为“免费”,供下一次分配使用。这就是VirtualQueryEx()无法工作的原因。
HeapWalk的问题在于你必须锁定堆(HeapLock),以便它可以在不改变堆分配的情况下运行它。这种锁可能会产生非常有害的副作用。引用:
走一堆可能会降级 性能,特别是对称性 多处理(SMP)计算机。该 副作用可能会持续到 过程结束。
即使这样,你得到的数字也毫无意义。程序永远不会耗尽可用空间,它会耗尽足够大的连续内存块来满足请求。我很害怕,没有快乐的答案。除了一个:64位操作系统的成本不到200美元。
答案 1 :(得分:0)
开始的地方可能是GetProcessMemoryInfo()。这将为您填充一个结构,其中包含当前工作集(以字节为单位)。
答案 2 :(得分:-1)
查看以下文章.NET and running processes
它使用WMI检查进程的内存使用情况,特别是使用
System.Diagnostics.Process
以及如何在C#中使用WMI的另一个链接:WMI Made Easy for C#
希望这有帮助。