【发布时间】: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.Parse和String.Substring的相对效率感到惊讶。如果您建议的ParseInt是 BCL 的一部分,那么它可能必须处理与Int32.Parse相同的可能性范围,例如不同的文化,NumberStyles和IFormatProvider选项。
标签: .net profiling memory-management