在研究内存使用时,GC_FOR_ALLOC更严重吗?

24

我目前正在调查我的Android应用程序中的垃圾回收问题,我很好奇是否GC_FOR_ALLOC比其他GC消息(例如GC_CONCURRENT)更能反映出一个更大的问题。

据我所知,GC_CONCURRENT正在执行垃圾回收器应该执行的操作。 堆已经达到了特定的限制,最好清理内存。

如果我正在尝试创建一个对象并且没有足够的内存来完成它,GC_FOR_ALLOC对我来说意味着有更严重的问题发生。

GC消息是否有优先级或“严重程度”级别?


你读过 https://dev59.com/HHNA5IYBdhLWcg3wmfO5 吗?被接受的答案中提到的链接可能会对你有所帮助。 - kommradHomer
@kommradHomer 感谢回复,但我认为这并不适用于这里,因为是 Dalvik 虚拟机将执行 GC 扫描。尽管如此,我仍然觉得这个链接是一个信息丰富、但有点晦涩的阅读材料。 - Andrew Weir
1个回答

55
从某种意义上说,GC_FOR_ALLOCGC_CONCURRENT更严重,因为GC_FOR_ALLOC意味着没有足够的空闲内存来满足分配请求,因此需要进行垃圾回收,而GC_CONCURRENT仅表示GC感觉到需要运行,通常是因为分配后可用的空闲内存量低于某个阈值。
但是,GC_FOR_ALLOC本身并不是应用程序出现问题的标志:
  • Android应用程序从小堆开始,当应用程序需要越来越多的内存时,堆的大小会增长(到一定程度),并在增加堆大小之前执行GC_FOR_ALLOC。在这种情况下,GC_FOR_ALLOC是完全正常的。
  • 如果您分配的内存比并发GC释放它的时间更快,则GC_FOR_ALLOC是不可避免的。快速分配内存并不一定有问题。
一个更严重的Android垃圾回收类型是GC_BEFORE_OOM,当分配请求失败甚至经过GC_FOR_ALLOC并且应用程序堆已经增长到允许的最大值时执行。当这种情况发生时,作为最后的手段,Dalvik将尝试在进行内存分配的最后一次尝试之前释放SoftReferences,如果仍然失败,则抛出OutOfMemory异常。

如果您想查看此逻辑的代码,请查看dalvik.git/vm/alloc/Heap.cpp中的tryMalloc()

无论如何,如果您不介意的话,我觉得查看logcat输出并不是调试垃圾回收问题最有效的方法。我不知道您遇到了什么具体问题,但您是否尝试过使用DDMS中的Allocation Tracker工具,并借助hprof-conv工具分析堆转储?(例如,请参见http://android-developers.blogspot.se/2011/03/memory-analysis-for-android.html以开始。)


感谢您的回复。我的应用程序已经在市场上运行了一段时间,我们正在对其进行一些微调。其中一个大问题是GC在4秒的时间窗口内运行了30次,这似乎过于频繁了。通过一些优化,现在GC只运行了6次 - 但是只有FOR_ALLOC被调用。但现在这是有意义的。 - Andrew Weir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接