2012-03-10 56 views
3

我正在爲android編寫一個實時遊戲,因此我希望儘可能地儘量減少分配/垃圾回收,正如在android「設計性能」開發者指南中推薦的那樣。Java GC在最小分配後運行非常頻繁

我有一個非常簡單的遊戲,它沒有使用太多內存(<根據hprof堆轉儲堆的2-3%),但是我的併發gc像發條一樣每7秒運行一次,總是釋放大約1MB的內存。我的遊戲已完全暫停,並且沒有做任何有趣的事情,並且運行分配跟蹤器5秒鐘,分配情況非常少。這是打開幾秒鐘後的分配跟蹤器轉儲的全部內容,它佔用的分配不到1kb(主要是達爾維克的東西以及我的鎖的鎖定/解鎖方法)。

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

你在使用任何迭代器嗎?取決於JVM結構的版本,像Collection中的Object可能會產生需要GC的對象。 – RussS 2012-03-10 06:53:51

+0

@RussS我習慣在foreach循環中使用它們,但是我試圖解決這個問題。當我使用它們時,我在分配跟蹤器中看到了數百個ArrayListIterator,但是因爲我刪除了它們,所以我不再看到它們。垃圾收集仍然存在:( – Tim 2012-03-10 08:26:19

+0

)您是否嘗試過在仿真器上運行以查看您是否得到相同的結果? – RussS 2012-03-10 16:41:03

回答

3

好吧,我發現泄漏。原來,我在一個浮點數組上大約每次運行50次就不必要地運行克隆,但真正讓我失望的是這並沒有出現在分配追蹤器中。

多一點研究表明我這thread,這似乎聲稱有一個Android錯誤,其中array.clone()操作不會顯示在分配跟蹤器中。

沮喪,花了我很長時間才找到它,但至少現在我只收集每秒1kb的<。