Java GC在最小分配后非常频繁地运行

时间:2012-03-10 05:50:09

标签: java android eclipse debugging

我正在为Android编写一个实时游戏,因此我想尽可能地按照androids" Performanceing for Performance"中的建议尽量减少分配/垃圾收集。开发者指南。

我有一个非常简单的游戏,它没有使用太多内存(根据hprof堆转储占用了2-3%的堆),但我的并发gc每隔7秒运行一次,总是释放大约1MB的内存。我的游戏完全暂停,没有做任何有趣的事情,运行分配跟踪器5秒显示很少的分配。这是打开几秒钟之后的整个分配跟踪器转储,它看起来占用的分配不到1kb(大多数只是dalvik的东西和我的锁定的锁定/解锁方法)。

19  24  byte[]  5   dalvik.system.NativeStart   run 
18  12  java.lang.Integer   5   java.lang.Integer   valueOf 
17  24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    
16  17  byte[]  5   android.ddm.DdmHandleHeap   handleREAQ  
15  24  org.apache.harmony.dalvik.ddmc.Chunk    5   android.ddm.DdmHandleHeap   handleREAQ  
14  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
13  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
12  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
11  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
10  28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
9   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
8   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
7   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
6   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
5   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
4   28  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node  10  java.util.concurrent.locks.AbstractQueuedSynchronizer   addWaiter   
3   24  byte[]  5   dalvik.system.NativeStart   run 
2   12  java.lang.Integer   5   java.lang.Integer   valueOf 
1   24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    

尽管如此,我每隔几秒钟就会看到大约1MB的收藏品:

03-09 21:41:56.665: D/dalvikvm(4210): GC_CONCURRENT freed 934K, 58% free 3069K/7175K, external 2847K/3550K, paused 3ms+2ms
03-09 21:42:03.685: D/dalvikvm(4210): GC_CONCURRENT freed 937K, 58% free 3069K/7175K, external 2847K/3550K, paused 3ms+1ms
03-09 21:42:10.705: D/dalvikvm(4210): GC_CONCURRENT freed 937K, 58% free 3069K/7175K, external 2847K/3550K, paused 5ms+2ms
03-09 21:42:17.715: D/dalvikvm(4210): GC_CONCURRENT freed 934K, 58% free 3069K/7175K, external 2847K/3550K, paused 3ms+1ms
03-09 21:42:24.725: D/dalvikvm(4210): GC_CONCURRENT freed 934K, 58% free 3069K/7175K, external 2847K/3550K, paused 2ms+3ms

我知道时间不多,但如果我可以避免,我不想从我的一个镜架中随机偷走10毫秒。我的问题是,如果我在分配跟踪器中看不到任何内容,那么只需几秒钟即可分配如此多的内存?我不会在电话的背景上想到任何东西,因为一旦我退出游戏,我就再也看不到GC了(或者很少见)。

我的渲染线程使用GLSurfaceView,这是暂停时唯一运行的东西,但我只是难以忘记我的记忆。

任何想法都表示赞赏。

1 个答案:

答案 0 :(得分:3)

好的,我发现了泄漏。事实证明我在一个浮点数组上不必要地运行了克隆每帧大约50次,但真正让我失望的是,这不会出现在分配跟踪器中。

更多的研究向我展示了这个thread,它似乎声称存在一个android错误,其中array.clone()操作不会出现在分配跟踪器中。

感到沮丧,我花了这么长时间才发现它,但至少现在我只收集每秒1kb。