为什么自己编写的页面总是在那里抖动_「内存抖动」?别再吓唬面试者们了行吗...
視頻版本
本文在 B 站有對(duì)應(yīng)的視頻,如果你喜歡看視頻版本,可以點(diǎn) 這里 去嗶哩嗶哩觀看,或者點(diǎn) 這里 去 YouTube 觀看。
從「內(nèi)存抖動(dòng)」說(shuō)起
面試官:你做過(guò)性能優(yōu)化是吧。面試者:嗯是的,在卡頓和耗電問(wèn)題上做過(guò)挺多事。
面試官:內(nèi)存抖動(dòng)的解決方案你有了解過(guò)嗎?
面試者:內(nèi)存什么?
面試官:內(nèi)存抖動(dòng)。沒有聽過(guò)嗎?
面試者:……沒有。
面試官:呼(搖頭)。年輕人還是要敬畏技術(shù)啊,要持續(xù)學(xué)習(xí)啊。
面試者:我……嗯……
大家好,我是扔物線朱凱。
看起來(lái)很酷的詞總是容易吸引眼球,比如「雙親委托」,比如「責(zé)任鏈」,比如——「內(nèi)存抖動(dòng)」。吸引眼球就意味著會(huì)有更多點(diǎn)擊,而點(diǎn)擊量是內(nèi)容創(chuàng)作者最愛的東西,所以這些名字很酷的詞就很自然地會(huì)受到各種技術(shù)文章的偏愛,因?yàn)槟銓戇@些文章可以得到更多的流量,這是無(wú)可厚非的。強(qiáng)調(diào)一下,這是無(wú)可厚非的。但有些作者對(duì)于流量的追求過(guò)于偏執(zhí),什么東西都喜歡過(guò)分地吹一下。
大家作為讀者,看文章的時(shí)候要有辨別力,不要被這些流量詞帶偏,更不要被某些流量販子們騙得去加到自己的面試題里來(lái)考驗(yàn)?zāi)愕拿嬖囌呤欠褡x過(guò)某篇文章,這是沒有價(jià)值的。
有價(jià)值,還是沒有?
啊啊?「內(nèi)存抖動(dòng)」這個(gè)概念竟然沒價(jià)值?
不是的 ,我不是說(shuō)內(nèi)存抖動(dòng)的概念沒價(jià)值。哎算了,我先說(shuō)一下什么是內(nèi)存抖動(dòng)吧:
在程序里,每創(chuàng)建一個(gè)對(duì)象,就會(huì)有一塊內(nèi)存分配給它;每分配一塊內(nèi)存,程序的可用內(nèi)存也就少一塊;當(dāng)程序被占用的內(nèi)存達(dá)到一定臨界程度,GC 也就是垃圾回收器(Garbage Collector)就會(huì)出動(dòng),來(lái)釋放掉一部分不再被使用的內(nèi)存。Android 里的 View.onDraw() 方法在每次需要重繪的時(shí)候都會(huì)被調(diào)用,這就意味著,如果你在 onDraw() 里寫了創(chuàng)建對(duì)象的代碼,在界面頻繁刷新的時(shí)候,你就也會(huì)頻繁創(chuàng)建出一大批只被使用一次的對(duì)象,這就會(huì)導(dǎo)致內(nèi)存占用的迅速攀升;然后很快,可能就會(huì)觸發(fā) GC 的回收動(dòng)作,也就是這些被你創(chuàng)建出來(lái)的對(duì)象被 GC 回收掉。垃圾內(nèi)存太多了就被清理掉,這是 Java 的工作機(jī)制,這不是問(wèn)題。問(wèn)題在于,頻繁創(chuàng)建這些對(duì)象會(huì)造成內(nèi)存不斷地攀升,在剛回收了之后又迅速漲起來(lái),那么緊接著就是又一次的回收,對(duì)吧?這么往復(fù)下來(lái),最終導(dǎo)致一種循環(huán),一種在短時(shí)間內(nèi)反復(fù)地發(fā)生內(nèi)存增長(zhǎng)和回收的循環(huán)。
這種循環(huán)往復(fù)的狀態(tài)就像是水波紋的顫動(dòng)一樣,它的專業(yè)稱呼叫做 Memory Churn,Android 的官方文檔里把它翻譯做了內(nèi)存抖動(dòng)。所以內(nèi)存抖動(dòng)其實(shí)并不是我們的內(nèi)存在整體地進(jìn)行搖晃這樣神奇的事情,
而僅僅是類似有一根攪拌棒輕輕地在內(nèi)存的邊界上進(jìn)行攪動(dòng)的樣子——其實(shí)翻譯成「內(nèi)存攪動(dòng)」好像也行哈?
我們也可以通過(guò) Android Studio 的 Memory Profiler 來(lái)更直觀地觀察到這種現(xiàn)象:
內(nèi)存的回收雖然很快,時(shí)間成本很低,但終究是有時(shí)間成本的。一兩次內(nèi)存回收不容易被用戶察覺,但多次內(nèi)存回收行為集中在短時(shí)間內(nèi)爆發(fā),這就造成了比較大的界面卡頓的風(fēng)險(xiǎn)。這也是為什么 Android 在官方文檔和 Android Studio 里都建議我們盡量避免在 onDraw() 里創(chuàng)建對(duì)象。
同樣的道理,不只是在 onDraw(),在次數(shù)比較大的循環(huán)里創(chuàng)建對(duì)象,同樣會(huì)導(dǎo)致內(nèi)存抖動(dòng)。不過(guò)因?yàn)樵趯?shí)踐中,我們?cè)?onDraw() 里創(chuàng)建的對(duì)象往往是繪制相關(guān)的對(duì)象,而這些對(duì)象又經(jīng)常會(huì)包含通往系統(tǒng)下層的 Native 對(duì)象的引用,這就導(dǎo)致在 onDraw() 里創(chuàng)建對(duì)象所導(dǎo)致的內(nèi)存回收的耗時(shí)往往會(huì)更高,直白地說(shuō)就是——界面更卡頓。
另外呢內(nèi)存抖動(dòng)有時(shí)候也會(huì)抖著抖著就變成內(nèi)存溢出了,這就是更嚴(yán)重的情況,因?yàn)閮?nèi)存溢出的直接結(jié)果就是軟件崩潰。
有價(jià)值,但「內(nèi)存抖動(dòng)」這幾個(gè)字不是關(guān)鍵
所以,「內(nèi)存抖動(dòng)」這個(gè)概念有價(jià)值嗎?
當(dāng)然有價(jià)值了,因?yàn)檫@個(gè)詞幫助我們很形象地去形容了程序中的一種現(xiàn)象。對(duì)吧?增加、回收、增加、回收。
那么我在開頭說(shuō)的「沒價(jià)值」,指的是什么呢?
我說(shuō)的不是「內(nèi)存抖動(dòng)」的概念沒價(jià)值,而是追求對(duì)這個(gè)概念本身的了解是沒價(jià)值的。確切地說(shuō)是,面試官們企圖用是否知道「內(nèi)存抖動(dòng)」這樣的詞來(lái)考察面試者是否具有高開發(fā)水平這樣的面試策略,是沒價(jià)值的。內(nèi)存優(yōu)化是一個(gè)很復(fù)雜很細(xì)碎的話題,而在 onDraw() 中避免創(chuàng)建對(duì)象只是其中的冰山一角。而且就算在這冰山一角里,重點(diǎn)也只在于「避免內(nèi)存增長(zhǎng)」,而不是「避免內(nèi)存抖動(dòng)」。內(nèi)存抖動(dòng)只是一種具體的表面現(xiàn)象而已,而這種現(xiàn)象背后的原因,除了在 onDraw() 中創(chuàng)建對(duì)象,也很少再有其他場(chǎng)景了。那么這種場(chǎng)景限定極強(qiáng)的詞被專門列出來(lái)在面試題里,又有什么意義呢?
當(dāng)我們問(wèn)「內(nèi)存抖動(dòng)」,我們應(yīng)該關(guān)心什么
我不是在說(shuō)你面試的時(shí)候不應(yīng)該問(wèn)內(nèi)存抖動(dòng),而是說(shuō)你的注意力一定不能放在這個(gè)詞上。聽沒聽說(shuō)過(guò)內(nèi)存抖動(dòng)并不重要,知道內(nèi)存抖動(dòng)的原因和解決方案才重要。
嗯……沒聽過(guò)內(nèi)存抖動(dòng),怎么會(huì)知道它的原因和解決方案?
他沒聽過(guò)你可以告訴他呀!不是不能問(wèn)內(nèi)存抖動(dòng),而是如果你問(wèn)了之后對(duì)方表示沒聽過(guò),你應(yīng)該進(jìn)一步引導(dǎo),比如你問(wèn)他:那么,Android 官方建議我們不要在 onDraw() 里創(chuàng)建對(duì)象你知道嗎?你知道為什么嗎?如果他立即回答這會(huì)導(dǎo)致頻繁觸發(fā)內(nèi)存回收,那不是證明他其實(shí)懂原理的嗎?這時(shí)候你再告訴他,這就叫內(nèi)存抖動(dòng),就行了。
而且也不要局限于這一個(gè)詞,你還可以繼續(xù)問(wèn):為什么在 onDraw() 里創(chuàng)建對(duì)象導(dǎo)致的結(jié)果是內(nèi)存抖動(dòng)而不是內(nèi)存溢出?這種對(duì)于能力的考察比對(duì)詞匯的考察重要多了。其實(shí)我也不是很確定這個(gè)問(wèn)題是不是每個(gè)喜歡問(wèn)內(nèi)存抖動(dòng)的面試官們都能回答上來(lái),但這樣問(wèn)才是考察程序員能力的最好方式。
如果你在面試時(shí)問(wèn)了內(nèi)存抖動(dòng),但在對(duì)方表示沒聽過(guò)之后,你就不再進(jìn)行任何的引導(dǎo)而是直接給對(duì)方扣了分,那你其實(shí)相當(dāng)于在問(wèn):我這里有一個(gè)高端詞匯,您聽過(guò)嗎?
自吹自擂
我在上課的時(shí)候,經(jīng)常跟學(xué)員強(qiáng)調(diào)學(xué)技術(shù)要學(xué)本質(zhì),因?yàn)橛行┑胤轿抑v得比較深我怕他們不學(xué)。說(shuō)到我的課,有想學(xué) Android 高級(jí)進(jìn)階系列化知識(shí)的,掃碼咨詢。
https://u.wechat.com/MDjgjMMWVLgiZjyvuqIYaa4 (二維碼自動(dòng)識(shí)別)
我怎么覺得我的廣告有點(diǎn)六學(xué)?過(guò)渡一點(diǎn)也不優(yōu)雅,強(qiáng)行轉(zhuǎn)彎,強(qiáng)勢(shì)恰飯。下次改進(jìn)下次改進(jìn)。最后
說(shuō)回到本質(zhì),學(xué)技術(shù)要學(xué)本質(zhì),但內(nèi)存抖動(dòng)并不是任何技術(shù)的本質(zhì)。其實(shí)我今天也并不是在聊內(nèi)存抖動(dòng)這個(gè)詞本身,而是想表達(dá)一種觀點(diǎn):
我們學(xué)技術(shù),應(yīng)該學(xué)得深,而且應(yīng)該足夠深,但不要被各種花里胡哨的詞嚇到,也不要被它們帶著跑,我們要有自己的知識(shí)體系,有自己的成長(zhǎng)邏輯。
我是扔物線,我不和你比高低,我只助你成長(zhǎng)。我們下期見。
總結(jié)
以上是生活随笔為你收集整理的为什么自己编写的页面总是在那里抖动_「内存抖动」?别再吓唬面试者们了行吗...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux 启动db2 服务器,Linu
- 下一篇: JAVA入门级教学之(访问修饰符权限控制