如何找到方法分配的内存量?

Posted

技术标签:

【中文标题】如何找到方法分配的内存量?【英文标题】:How do I find the amount of memory allocated by a method? 【发布时间】:2011-02-24 03:34:21 【问题描述】:

我想知道方法运行时分配的内存总量。到目前为止,我有:

GC.Collect()
GC.WaitForPendingFinalizers()
memStart = GC.GetTotalMemory(false)
f()
memEnd = GC.GetTotalMemory(false)
print (memEnd - memStart)

这对于简单的函数来说似乎工作得很好,但是当f 分配太多以至于它强制收集时,结果会排除已经收集的对象。不仅如此,没有办法说这个“溢出”发生了。

有没有简单的方法来做到这一点?无需购买/安装/配置内存分析器?像分配器/收集器的秒表这样的东西是理想的。所以我可以这样做:

sw = new GCStopwatch()
sw.Start()
f()
sw.Stop()
print sw.TotalBytesAllocated
print sw.NumberOfCollections
// etc

我想要这个,这样我就可以知道一个方法给垃圾收集器带来了多大的压力。我的代码是使用大量调用Int32.Parse(s.Substring(4,6)) 从固定长度字符串中读取数字,我考虑通过引入ParseInt(String s, int startIndex, int length) 来进行就地解析以避免分配数以万计的子字符串。但这在其他场景中也是一个不错的工具。

【问题讨论】:

如果f 分配了很多小对象,从而导致了一个集合,并且这些对象中的很多被释放了......很好 - .NET 内存系统运行良好,并且其中一个它的主要假设 - 可以释放许多最近分配的对象。换句话说,你为什么要猜测分配器和垃圾收集器? @Damien:我不想以任何方式猜测或影响 GC。我只想要一些关于给定时期内分配/收集的统计信息,即。一个轻量级的分析类。 @petebu - 我更关注您的最后一段,您正在考虑重写框架功能以避免分配这些子字符串。 @Damien:但选择是在大量短期的小分配和以极低的成本根本没有分配之间进行选择。 ParseInt 与 Int32.Parse 一样具有可读性,并且实现非常简单并且永远不会改变(零维护)。我没有反对 .NET 内存系统,但在这种情况下,分配似乎是无偿的。换句话说,如果 ParseInt 是 BCL 的一部分,那么这将是没有道理的。 @petebu - 当你找到你喜欢的分析器时,你可能会对Int32.ParseString.Substring 的相对效率感到惊讶。如果您建议的 ParseInt 是 BCL 的一部分,那么它可能必须处理与 Int32.Parse 相同的可能性范围,例如不同的文化,NumberStylesIFormatProvider 选项。 【参考方案1】:

我一直使用性能计数器进行此类分析。不完美,但通常足够好。

GC.Collect()
GC.WaitForPendingFinalizers()

这两行不会等待垃圾收集器真正完成。无论如何,在您调用函数期间可能会发生垃圾收集。将性能/时间作为优化来衡量可能会更好。

【讨论】:

【参考方案2】:

我知道您说过您不想使用内存分析器,但这正是一种有用的情况。只需下载类似ANTS Memory Profiler 的东西,然后使用 14 天免费试用。它应该让您对正在发生的事情有一个相当即时的了解。

【讨论】:

以上是关于如何找到方法分配的内存量?的主要内容,如果未能解决你的问题,请参考以下文章

如何找出分配给 javascript 对象的内存量? [复制]

C++。如何获得进程从一开始就分配的最大内存量?

JVM是如何分配管理内存的?

3.内存分配逃逸分析与栈上分配直接内存和运行时常量池基本类型的包装类和常量池TLAB可达性分析算法(学习笔记)

JVM学习之内存分配和垃圾回收

确定特定 .NET 程序集分配的内存量