如果你是 Android 開發(fā)者惕虑,一定聽過“內存抖動”這個詞忙迁,如果高頻地申請較大尺寸的內存贤牛,則可能導致短時間內頻繁觸發(fā) GC构蹬,造成內存的頻繁申請和釋放王暗,使用Profiler查看內存使用時,看起來就是一個抖動的曲線庄敛。
學習自定義View的時候,估計會有老師傅和你說:
不要在 onDraw() 里創(chuàng)建對象, 因為這個函數調用特別頻繁铐姚,容易引起內存抖動策肝。
你當然不會在編碼的時候這么做,今天我想看看隐绵,到底能“抖”成什么樣子之众。。依许。
測試代碼
測試代碼如下棺禾,每次 onDraw()
都會創(chuàng)建一個20MB 的大對象,這里要注意:不建議使用 Bitmap 作為測試對象峭跳,因為在不同的 Android 版本 Bitmap 像素數據存儲的位置不同膘婶,這會為測試添加新的變量。
override fun onDraw(canvas: Canvas?) {
if (flag) {
Trace.beginSection("MemoryThrashingView --> alloc")
val start = System.currentTimeMillis()
largeObject = LargeObject()
Log.d(TAG, "alloc onDraw: ${System.currentTimeMillis() - start}")
invalidate()
Trace.endSection()
}
}
//LargeObject
class LargeObject {
private int _20MB = 20 * 1024 * 1024;
private byte[] memory = new byte[_20MB];
}
測試設備
為了保證變量單一蛀醉,測試統(tǒng)一使用模擬器悬襟,選擇了Android 4.4、Android 5.0拯刁、Android 8.1 三個版本脊岳,每個版本又分為256MB 和 512MB 兩個最大堆限制。
測試結果
Android 4.4 - 256MB heap
Android 4.4 - 512MB heap
Android 5.0 - 256MB heap
Android 5.0 - 512MB heap
Android 8.1 - 256MB heap
Android 8.1 - 512MB heap
我們可以看到,Kitkat(Dalvik) 在內存抖動的場景表現(xiàn)是災難級的割捅,每一幀都延時奶躯,掉幀非常嚴重。ART 的表現(xiàn)要好很多亿驾,1秒內會有1次到幾次的延時嘹黔,同時,由于Lollipop的分代管理策略莫瞬,在這個場景表現(xiàn)甚至優(yōu)于Android 8.1 的CC参淹。
后記:
其實我也不清楚自己得出的結論有沒有那么可靠,畢竟為了方便控制變量乏悄,我統(tǒng)一使用了模擬器來測試浙值,但我發(fā)現(xiàn)當前電腦的負載情況也影響著模擬器的性能表現(xiàn),同一個模擬器性能差異巨大檩小,后來我將電腦的內存使用控制在60%左右开呐,對比了256MB和512MB的性能表現(xiàn),其實增加了幾倍的測試工作量规求,希望能夠客觀一些筐付。