我正在为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,这是暂停时唯一运行的东西,但我只是难以忘记我的记忆。
任何想法都表示赞赏。
答案 0 :(得分:3)
好的,我发现了泄漏。事实证明我在一个浮点数组上不必要地运行了克隆每帧大约50次,但真正让我失望的是,这不会出现在分配跟踪器中。
更多的研究向我展示了这个thread,它似乎声称存在一个android错误,其中array.clone()操作不会出现在分配跟踪器中。
感到沮丧,我花了这么长时间才发现它,但至少现在我只收集每秒1kb。