我有一个正在运行的C# XNA WP7项目,发现在屏幕切换期间会消耗内存并且没有释放,最终导致内存不足异常。
我已经找了很久,但一直找不到内存去哪了。
有没有办法找出内存使用的位置及为什么没有被返还给设备呢?
谢谢任何帮助!
我已经找了很久,但一直找不到内存去哪了。
有没有办法找出内存使用的位置及为什么没有被返还给设备呢?
谢谢任何帮助!
在 Windows 版本的项目上使用 Microsoft 的 .NET Framework 4 CLR Profiler (免费)。
使用它可以获得项目内存分配的时间轴。或者您可以直接检查堆(heap)本身。它会给出按类型分配的所有对象列表。您可能会看到您正在过度分配的对象,然后您可以为该类型或时间范围引出一个分配图表。这将显示分配这些对象的函数。
这里有一篇随机博客文章,其中包含一些 CLR Profiler 的截图和讨论。(虽然不是完全与您所用相同,但如果您以前从未使用过 CLR Profiler,则会有用的介绍。)
然而:由于您使用的是 XNA,并且通常需要尝试很多次才能使 C#耗尽托管内存,因此您可能会耗尽了非托管内存。是否有某个地方在您停止使用已创建的图形或声音对象之前没有调用Dispose()
?我已经在这里多次讨论了这个问题的细节。
因此,只需注意,如果 CLR Profiler 中显示了许多非常小的对象,则它们实际上可能正在使用大量的非托管内存。
mono --profile=log program.exe
program.exe
退出后,它会留下一个分析器文件(默认为output.mlpd
),要读取收集的信息,请使用:mprof-report output.mlpd
例如,我执行mprof-report output.mlpd | vim -
。
默认情况下,它会收集许多不同的信息。在输出的开头处(给定默认设置),您将看到按“分配”列排序的函数表,例如:
Allocation summary
24 Bytes Count Average Type name
25 7357392 306558 24 System.IntPtr
26 6677904 139123 48 System.Collections.ArrayList.ArrayListEnumeratorSimple
27 5842736 136185 42 Mono.Unix.Native.Syscall._pollfd[]
28 3078176 49566 62 System.Byte[]
29 2574504 38057 67 System.String
30 908320 14803 61 System.Int32[]
31 719984 5294 136 Mono.Globalization.Unicode.SortKeyBuffer
我对它的优点印象深刻:
ContentManager
是IDisposable
的,所以需要处理它),你应该Dispose()
任何你创建的IDisposable
对象。我在此答案的结尾有一个使用内容管理器的完整信息栈。注意,ContentManager
会处理加载的所有内容对象。 - Andrew RussellLoad()
的所有内容。如果您尝试使用一个ContentManager多次加载某个内容,您总是会得到相同的对象(它会保留列表)。但是,如果您有多个ContentManagers,则它们彼此不知道,并且每个ContentManager在您第一次请求时都需要加载自己的内容副本。在ContentManager上调用Dispose
或Unload
将处理它加载的所有内容,但对其他ContentManagers或内容没有影响。 - Andrew Russell