chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Android內(nèi)存優(yōu)化的常用工具與手段

Linux愛好者 ? 來(lái)源:掘金 ? 作者:RicardoMJiang ? 2021-11-19 10:41 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

內(nèi)存問(wèn)題是一個(gè)普遍問(wèn)題,但是卻普遍缺少關(guān)注度,具體有以下幾個(gè)原因:

內(nèi)存問(wèn)題相對(duì)比較隱蔽,表現(xiàn)并不明顯。

同時(shí)android使用Jvm語(yǔ)言開發(fā),垃圾回收是自動(dòng)的,所以一般沒(méi)有特別關(guān)注。

內(nèi)存問(wèn)題難以定位,出現(xiàn)問(wèn)題的地方往往只是表現(xiàn)的地方,真正的原因難以收集。

內(nèi)存優(yōu)化的內(nèi)容其實(shí)非常多而復(fù)雜,我們可以嘗試從以下思路去了解:

要了解內(nèi)存問(wèn)題,我們首先要了解為什么要做內(nèi)存優(yōu)化?

同時(shí)需要了解一些內(nèi)存優(yōu)化的背景知識(shí),如垃圾回收機(jī)制。

我們需要了解一些內(nèi)存優(yōu)化的常用工具與手段。

圖片是內(nèi)存優(yōu)化的重點(diǎn),我們需要重點(diǎn)了解下圖片優(yōu)化的知識(shí)點(diǎn)。

內(nèi)存問(wèn)題的一個(gè)直接體現(xiàn)是OOM,我們還需要了解下OOM治理的一些手段。

所以我們可以輕松得出本文的主要內(nèi)容:

為什么要做內(nèi)存優(yōu)化?

android內(nèi)存優(yōu)化的一些背景知識(shí)。

android內(nèi)存優(yōu)化的常用工具與手段。

怎么做圖片內(nèi)存優(yōu)化?

怎么做OOM線上監(jiān)控?

本文主要內(nèi)容思維導(dǎo)圖如下:

1、為什么要做內(nèi)存優(yōu)化?

要回答這個(gè)問(wèn)題,我們首先應(yīng)該明確需求,當(dāng)我們?nèi)プ鰞?nèi)存優(yōu)化時(shí)是為了什么。

做內(nèi)存優(yōu)化的目的是降低OOM率、減少卡頓、增加應(yīng)用存活時(shí)間。

1.1 降低OOM率

做內(nèi)存優(yōu)化的一個(gè)常見原因是為了降低OOM率。

申請(qǐng)內(nèi)存過(guò)多而沒(méi)有及時(shí)釋放,常常就會(huì)導(dǎo)致OOM。

引起OOM的原因有多種,在后面我們?cè)偌?xì)談。

1.2 減少卡頓

Android中造成界面卡頓的原因有很多種,其中一種就是由內(nèi)存問(wèn)題引起的。

內(nèi)存問(wèn)題之所以會(huì)影響到界面流暢度,是因?yàn)槔厥铡?/p>

在GC時(shí),所有線程都要停止,包括主線程。當(dāng)GC和繪制界面的操作同時(shí)觸發(fā)時(shí),繪制的執(zhí)行就會(huì)被擱置,導(dǎo)致掉幀,也就是界面卡頓。

1.3 增加應(yīng)用存活時(shí)間

Android會(huì)按照特定的機(jī)制清理進(jìn)程,清理進(jìn)程時(shí)優(yōu)先會(huì)考慮清理后臺(tái)進(jìn)程,如果某個(gè)應(yīng)用在后臺(tái)運(yùn)行并且占用的內(nèi)存更多,就會(huì)被優(yōu)先清理掉。

我們通常希望App能盡量存活的久一點(diǎn),所以內(nèi)存不再使用時(shí)應(yīng)該盡快釋放。

2、android內(nèi)存優(yōu)化的一些背景知識(shí)

2.1 Java垃圾回收機(jī)制

Java內(nèi)存回收主要包括以下內(nèi)容:

判斷對(duì)象是否回收的可達(dá)性分析算法。

強(qiáng)軟弱虛4種引用類型。

用于GC回收的垃圾回收算法。

這些都是很常見的知識(shí)點(diǎn)了,這里也就不綴述了,如果想要了解更多細(xì)節(jié)的同學(xué)可參考:Java 垃圾回收機(jī)制。

https://juejin.cn/post/6844903897958449166

2.2 什么是內(nèi)存泄漏?

內(nèi)存泄漏指的是一塊內(nèi)存沒(méi)有被使用且無(wú)法被GC回收,從而造成了內(nèi)存的浪費(fèi),比如Handler匿名內(nèi)部類持有Activity的引用,Activity 需要銷毀時(shí),GC 就無(wú)法回收它。

內(nèi)存泄漏的表現(xiàn)就是可用內(nèi)存逐漸減少,無(wú)法被回收的內(nèi)存逐漸累積,直到應(yīng)用無(wú)更多可用內(nèi)存可申請(qǐng)時(shí),就會(huì)導(dǎo)致內(nèi)存溢出。

內(nèi)存泄漏的直接原因是長(zhǎng)生命周期的對(duì)象引用了短生命周期的對(duì)象,導(dǎo)致短生命周期對(duì)象無(wú)法回收。

常見的引起內(nèi)存泄漏的原因有:

非靜態(tài)內(nèi)部類持有了外部引用。

靜態(tài)變量持有了context的引用。

資源沒(méi)有及時(shí)釋放。

我們一般使用LeakCanary或者Profile檢測(cè)內(nèi)存泄漏。

2.3 什么是內(nèi)存抖動(dòng)?

當(dāng)我們?cè)诙虝r(shí)間內(nèi)頻繁創(chuàng)建大量臨時(shí)對(duì)象時(shí),就會(huì)引起內(nèi)存抖動(dòng),比如在一個(gè)for循環(huán)中創(chuàng)建臨時(shí)對(duì)象實(shí)例,下面這張圖就是內(nèi)存抖動(dòng)時(shí)的一個(gè)內(nèi)存圖表現(xiàn),它的形狀是鋸齒形的,而中間的垃圾桶代表著一次GC。

內(nèi)存抖動(dòng)意味著頻繁的創(chuàng)建對(duì)象與回收,容易觸發(fā)GC,而當(dāng)GC時(shí)所有線程都會(huì)停止,因此可能導(dǎo)致卡頓。

為了避免內(nèi)存抖動(dòng),我們應(yīng)該避免以下操作:

盡量避免在循環(huán)體中創(chuàng)建對(duì)象。

盡量不要在自定義View的onDraw()方法中創(chuàng)建對(duì)象,因?yàn)檫@個(gè)方法會(huì)被頻繁調(diào)用。

對(duì)于能夠復(fù)用的對(duì)象,可以考慮使用對(duì)象池把它們緩存起來(lái)。

2.4 什么是內(nèi)存溢出?

內(nèi)存溢出即申請(qǐng)的內(nèi)存超出可用的內(nèi)存,即OOM,這會(huì)導(dǎo)致我們的程序異常退出,這也是我們重點(diǎn)關(guān)注的指標(biāo)。

引起OOM的原因可能有多種,主要可以分為以下幾類:

275c591c-43cb-11ec-b939-dac502259ad0.png

關(guān)于OOM治理及線上監(jiān)控等,后面會(huì)詳細(xì)介紹。

3、android內(nèi)存優(yōu)化的常用工具與手段

3.1 Memory Profiler

Memory Profiler是Profiler 中的其中一個(gè)版塊,Profiler 是 Android Studio 為我們提供的性能分析工具,使用 Profiler 能分析應(yīng)用的 CPU、內(nèi)存、網(wǎng)絡(luò)以及電量的使用情況。

使用Memory可以檢測(cè)以下功能:

查看內(nèi)存曲線及內(nèi)存占用情況。

可以定位是否存在內(nèi)存抖動(dòng)問(wèn)題。

堆轉(zhuǎn)儲(chǔ)(Dump Java Heap)可檢測(cè)出內(nèi)存泄漏的對(duì)象。

關(guān)于Memory Profiler的具體使用就不在此綴述了,想要了解的可參考:什么是 Memory Profiler?

https://juejin.cn/post/6844903897958449166

3.2 Memory Analyzer Tool

MAT工具可以幫助開發(fā)者定位導(dǎo)致內(nèi)存泄漏的對(duì)象,以及發(fā)現(xiàn)大的內(nèi)存對(duì)象,然后解決內(nèi)存泄漏并通過(guò)優(yōu)化內(nèi)存對(duì)象,以達(dá)到減少內(nèi)存消耗的目的。

比起Memory Profiler,MAT使用起來(lái)更加麻煩,同時(shí)現(xiàn)在Memory Profiler功能也越來(lái)越強(qiáng)大了,所以我現(xiàn)在已經(jīng)很少使用MAT了。

如果想要更多地了解MAT,也可以參考:什么是Memory Analyzer Tool。

https://juejin.cn/post/6844903897958449166#heading-52

3.3 LeakCanary檢測(cè)內(nèi)存泄漏

相比Memory Profiler與MAT,LeakCanary在使用上更加簡(jiǎn)便。

只需要在項(xiàng)目中添加依賴,即可自動(dòng)地檢測(cè)內(nèi)存泄漏并報(bào)警,使用起來(lái)非常方便。

LeakCanary有以下幾個(gè)特點(diǎn):

不需要手動(dòng)初始化。

可自動(dòng)檢測(cè)內(nèi)存泄漏并通過(guò)通知報(bào)警。

不能用于線上。

LeakCanary檢測(cè)流程如下

關(guān)于LeakCanary的原理,我之前曾經(jīng)總結(jié)過(guò)一篇文章,有興趣的同學(xué)也可以參考:【帶著問(wèn)題學(xué)】關(guān)于LeakCanary2.0你應(yīng)該知道的知識(shí)點(diǎn)。

https://juejin.cn/post/6968084138125590541

3.4 內(nèi)存優(yōu)化的一些常規(guī)手段

內(nèi)存優(yōu)化的一些細(xì)節(jié)問(wèn)題可以在開發(fā)時(shí)避免,下面介紹一些常規(guī)的內(nèi)存優(yōu)化手段。

1)、使用LargeHeap屬性增加最大可用內(nèi)存。

2)、在系統(tǒng)觸發(fā)資源緊張回調(diào)時(shí),主動(dòng)刪除緩存。

3)、使用優(yōu)化過(guò)后的集合:如SparseArray類等。

4)、謹(jǐn)慎使用 SharedPreference,SP會(huì)在應(yīng)用初始化時(shí)將所有內(nèi)容加載到內(nèi)存中,所以不應(yīng)該存放比較大的內(nèi)容。

5)、謹(jǐn)慎使用外部庫(kù),引入時(shí)需要明確不會(huì)對(duì)應(yīng)用性能造成大的影響。

6)、業(yè)務(wù)架構(gòu)設(shè)計(jì)要合理,抽象可以優(yōu)化代碼的靈活性和可維護(hù)性,但是抽象也會(huì)帶來(lái)其他成本,應(yīng)權(quán)衡使用。

這些細(xì)節(jié)問(wèn)題其實(shí)都很普通,如果平時(shí)注意到了,相信對(duì)應(yīng)用的內(nèi)存一定有所幫助。

4、怎么做圖片內(nèi)存優(yōu)化?

內(nèi)存優(yōu)化應(yīng)該優(yōu)先去做見效快的地方,圖片內(nèi)存優(yōu)化是內(nèi)存優(yōu)化的重點(diǎn),可能一張圖片沒(méi)有回收就會(huì)造成幾M內(nèi)存的浪費(fèi)。

4.1 常規(guī)的圖片內(nèi)存優(yōu)化方法

我們都知道,圖片所占內(nèi)存=寬高一像素占用內(nèi)存。

所以優(yōu)化圖片內(nèi)存主要有以下幾個(gè)思路:

縮放減小寬高。

減少每個(gè)像素所占用的內(nèi)存。

內(nèi)存復(fù)用,避免重復(fù)分配內(nèi)存。

對(duì)于大圖,可以采取局部加載的策略。

4.1.1 減少圖片寬高

有時(shí)圖片寬高為200*200, 而View寬高為100*100, 這種時(shí)候如果展示200*200的圖片沒(méi)有意義,應(yīng)該對(duì)圖片進(jìn)行縮放。

這種情況一般通過(guò)inSampleSize實(shí)現(xiàn)。

BitampFactory.Options options = new BitmapFactory.Options();

// 設(shè)置為4就是寬和高都變?yōu)樵瓉?lái)1/4大小的圖片

options.inSampleSize = 4;

BitmapFactory.decodeSream(is, null, options);

4.1.2 減少每個(gè)像素所占用的內(nèi)存

在API29中,將Bitmap分為ALPHA_8, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE六個(gè)等級(jí)。

ALPHA_8:不存儲(chǔ)顏色信息,每個(gè)像素占1個(gè)字節(jié);

RGB_565:僅存儲(chǔ)RGB通道,每個(gè)像素占2個(gè)字節(jié),對(duì)Bitmap色彩沒(méi)有高要求,可以使用該模式;

ARGB_4444:已棄用,用ARGB_8888代替;

ARGB_8888:每個(gè)像素占用4個(gè)字節(jié),保持高質(zhì)量的色彩保真度,默認(rèn)使用該模式;

RGBA_F16:每個(gè)像素占用8個(gè)字節(jié),適合寬色域和HDR;

HARDWARE:一種特殊的配置,減少了內(nèi)存占用同時(shí)也加快了Bitmap的繪制。

每個(gè)等級(jí)每個(gè)像素所占用的字節(jié)也都不一樣,所存儲(chǔ)的色彩信息也不同。同一張100像素的圖片,ARGB_8888就占了400字節(jié),RGB_565才占200字節(jié)。

所以在某些場(chǎng)景中,修改圖片格式可以達(dá)到減少一半內(nèi)存的效果。

4.1.3 內(nèi)存復(fù)用,避免重復(fù)分配內(nèi)存

Bitmap所占內(nèi)存比較大,如果我們頻繁創(chuàng)建與回收Bitmap,那么很容易造成內(nèi)存抖動(dòng),所以我們應(yīng)該盡量復(fù)用Bitmap內(nèi)存。

在 Android 3.0(API 級(jí)別 11)開始,系統(tǒng)引入了BitmapFactory.Options.inBitmap字段。如果設(shè)置了此選項(xiàng),那么采用 Options 對(duì)象的解碼方法會(huì)在生成目標(biāo) Bitmap 時(shí)嘗試復(fù)用 inBitmap,這意味著 inBitmap 的內(nèi)存得到了重復(fù)使用,從而提高了性能,同時(shí)移除了內(nèi)存分配和取消分配。

不過(guò) inBitmap 的使用方式存在某些限制,在 Android 4.4(API 級(jí)別 19)之前系統(tǒng)僅支持復(fù)用大小相同的位圖,4.4 之后只要 inBitmap 的大小比目標(biāo) Bitmap 大即可。

4.1.4 大圖局部加載策略

對(duì)于圖片加載還有種情況,就是單個(gè)圖片非常巨大,并且還不允許壓縮。比如顯示:世界地圖、清明上河圖、微博長(zhǎng)圖等。

首先不壓縮,按照原圖尺寸加載,那么屏幕肯定是不夠大的,并且考慮到內(nèi)存的情況,不可能一次性整圖加載到內(nèi)存中。

所以這種情況的優(yōu)化思路一般是局部加載,通過(guò)BitmapRegionDecoder來(lái)實(shí)現(xiàn)。

//設(shè)置顯示圖片的中心區(qū)域

BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, false);

BitmapFactory.Options options = new BitmapFactory.Options();

options.inPreferredConfig = Bitmap.Config.RGB_565;

Bitmap bitmap = bitmapRegionDecoder.decodeRegion(new Rect(width / 2 - 100, height / 2 - 100, width / 2 + 100, height / 2 + 100), options);

mImageView.setImageBitmap(bitmap);

4.1.5 小結(jié)

上面所說(shuō)的這些關(guān)于Bitmap的內(nèi)存優(yōu)化策略其實(shí)都比較簡(jiǎn)單,而且我們?cè)陂_發(fā)中可能很少用到

因?yàn)槲覀兂S玫膱D片框架比如Glide已經(jīng)將這些都封裝在里面了,所以一般情況下我們加載圖片時(shí)不需要做這些特殊操作。

關(guān)于Glide對(duì)于加載圖片都做了哪些優(yōu)化,有興趣的同學(xué)可以參考:【帶著問(wèn)題學(xué)】Glide做了哪些優(yōu)化?

https://juejin.cn/post/6970683481127043085

4.2 圖片兜底策略

針對(duì)因activity、fragment泄漏導(dǎo)致的圖片泄漏,我們可以在onDetachedFromWindow時(shí)機(jī)進(jìn)行了監(jiān)控和兜底,具體流程如下:

通過(guò)這種方式可以方便地解決因Activity導(dǎo)致的圖片泄漏問(wèn)題。

4.3 線上大圖監(jiān)控方案

當(dāng)運(yùn)營(yíng)在線上配置了不合理大小的圖片時(shí),如果我們及時(shí)發(fā)現(xiàn),也會(huì)帶來(lái)內(nèi)存問(wèn)題。

如果圖片本身大小就不合理,我們?cè)谶@個(gè)基礎(chǔ)上談圖片優(yōu)化也沒(méi)有什么意義,因此大圖監(jiān)控這也是個(gè)比較常見的需求。

下面介紹幾種大圖監(jiān)控的方案:

4.3.1 ArtHook 方案

該方案采用weishu大佬寫的epic庫(kù)實(shí)現(xiàn),通過(guò)對(duì)ART虛擬機(jī)的hook,hook ImageView的 setImageBitmap 等方法。

解析對(duì)比方法參數(shù)中的 bitmap 寬高和 ImageView 實(shí)例的寬高,也可以獲得bitmap的實(shí)際大小。

如果圖片寬高比ImageView寬高大,或者圖片大小超出了閾值,就可以把相關(guān)信息上報(bào)。

這種方案的優(yōu)點(diǎn)在于:

侵入性極低,一次初始化配置即可hook全局的目標(biāo)View控件。

可以獲取代碼調(diào)用堆棧,方便開發(fā)者快速定位。

而缺點(diǎn)則在于:

兼容性存在問(wèn)題,使用了hook系統(tǒng)API ,不能用于線上。

4.3.2 BaseActivity 方案

大部分應(yīng)用工程在業(yè)務(wù)發(fā)展的過(guò)程中都會(huì)沉淀封裝自己的BaseActivity ,通過(guò)在BaseActivity onDestroy中動(dòng)態(tài)地檢測(cè)各個(gè)View控件,從而獲知圖片加載情況。

class BaseActivity : Activity(){

fun onDestory(){

if(isOpenCheckBitmap){

checkBitmapFromView()

}

}

fun checkBitmapFromView(){

//1、遍歷activity中的各個(gè)View控件

//2、獲取View控件加載的Bitmap

//3、對(duì)比Bitmap寬高與View寬高

}

}

這種方案的優(yōu)點(diǎn)在于:

兼容性強(qiáng),無(wú)任何反射。

加入簡(jiǎn)單,沒(méi)有什么復(fù)雜邏輯。

缺點(diǎn)在于:

侵入性太強(qiáng),需要修改BaseActivity。

BaseActivity.onDestory本身可能被重寫,并不安全。

4.3.3 ASM方案

該方案在編譯流程進(jìn)行插樁,通過(guò)匹配setImageBitmap、 setBackground等關(guān)鍵方法,插入Bitmap大小檢測(cè)邏輯。

這種方案優(yōu)點(diǎn)在于:

編譯時(shí)期插樁,對(duì)開發(fā)過(guò)程無(wú)侵入性。

缺點(diǎn)在于:

通過(guò)插樁的方式打點(diǎn),可能會(huì)增加編譯期耗時(shí)。

ASM代碼維護(hù)成本較高,使用起來(lái)不是那么方便。

4.3.4 registerActivityLifecycleCallback方案

通過(guò)registerActivityLifecycleCallback監(jiān)聽Activity生命周期,在onStop時(shí)進(jìn)行Bitmap大小檢測(cè)的邏輯。

private fun registerActivityLifecycleCallback(application: Application) {

application.registerActivityLifecycleCallbacks(object :

Application.ActivityLifecycleCallbacks {

override fun onActivityStopped(activity: Activity) {

checkBitmapIsTooBig(childViews)

}

})

}

這種方案對(duì)原始代碼無(wú)侵入性,同時(shí)使用起來(lái)比較簡(jiǎn)單,也沒(méi)有兼容性問(wèn)題,應(yīng)該屬于比較良好的方案。

詳細(xì)實(shí)現(xiàn)可見:BitmapCanary 誕生。

https://juejin.cn/post/6956138531789996040#heading-14

5、怎么做OOM線上監(jiān)控?

上文我們介紹了,可以使用LeakCanary在線下監(jiān)測(cè)內(nèi)存泄漏,但是LeakCanary只能在線下使用,有以下問(wèn)題:

線下場(chǎng)景能跑到的場(chǎng)景有限,很難把所有用戶場(chǎng)景窮盡。碰到線上問(wèn)題難以定位。

檢測(cè)過(guò)程需要主動(dòng)觸發(fā)GC,Dump內(nèi)存鏡像造成app凍結(jié),造成測(cè)試過(guò)程中體驗(yàn)不好。

適用范圍有限,只能定位Activity&Fragment泄漏,無(wú)法定位大對(duì)象、頻繁分配等問(wèn)題。

hprof文件過(guò)大,如果整體上傳的話需要耗費(fèi)很多資源。

下面我們就介紹一下快手開源的線上OOM監(jiān)控框架KOOM。

5.1 線上OOM監(jiān)控框架KOOM介紹

上面我們介紹了LeakCanary不能用于線上監(jiān)控的原因,所以要實(shí)現(xiàn)線上監(jiān)控功能,就需要解決以下問(wèn)題:

1、監(jiān)控

主動(dòng)觸發(fā)GC,會(huì)造成卡頓

2、采集

Dump hprof,會(huì)造成app凍結(jié)

Hprof文件過(guò)大

3、解析

解析耗時(shí)過(guò)長(zhǎng)

解析本身有OOM風(fēng)險(xiǎn)

其核心流程為三部分:

監(jiān)控OOM,發(fā)生問(wèn)題時(shí)觸發(fā)內(nèi)存鏡像的采集,以便進(jìn)一步分析問(wèn)題。

采集內(nèi)存鏡像,學(xué)名堆轉(zhuǎn)儲(chǔ),將內(nèi)存數(shù)據(jù)拷貝到文件中,以下簡(jiǎn)稱dump hprof。

解析鏡像文件,對(duì)泄漏、超大對(duì)象等我們關(guān)注的對(duì)象進(jìn)行可達(dá)性分析,解析出其到GC root的引用鏈以解決問(wèn)題。

5.2 KOOM解決GC卡頓

LeakCanary通過(guò)多次GC的方式來(lái)判斷對(duì)象是否被回收,所以會(huì)造成性能損耗。

koom通過(guò)無(wú)性能損耗的內(nèi)存閾值監(jiān)控來(lái)觸發(fā)鏡像采集,具體策略如下:

1、Java堆內(nèi)存/線程數(shù)/文件描述符數(shù)突破閾值觸發(fā)采集。

2、Java堆上漲速度突破閾值觸發(fā)采集。

3、發(fā)生OOM時(shí)如果策略1、2未命中 觸發(fā)采集。

4、泄漏判定延遲至解析時(shí)。

我們并不需要在運(yùn)行時(shí)判定對(duì)象是否泄漏,以Activity為例,我們并不需要在運(yùn)行時(shí)判定其是否泄漏,Activity有一個(gè)成員變量mDestroyed,在onDestory時(shí)會(huì)被置為true,只要解析時(shí)發(fā)現(xiàn)有可達(dá)且mDestroyed為true的Activity,即可判定為泄漏。

通過(guò)將泄漏判斷延遲至解析時(shí),即可解決GC卡頓的問(wèn)題。

5.3 KOOM解決Dump hprof凍結(jié)app

Dump hprof即采集內(nèi)存鏡像需要暫停虛擬機(jī),以確保在內(nèi)存數(shù)據(jù)拷貝到磁盤的過(guò)程中,引用關(guān)系不會(huì)發(fā)生變化,暫停時(shí)間通常長(zhǎng)達(dá)10秒以上,對(duì)用戶來(lái)講是難以接受的,這也是LeakCanary官方不推薦線上使用的重要原因之一。

利用Copy-on-write機(jī)制,fork子進(jìn)程dump內(nèi)存鏡像,可以完美解決這一問(wèn)題,fork成功以后,父進(jìn)程立刻恢復(fù)虛擬機(jī)運(yùn)行,子進(jìn)程dump內(nèi)存鏡像期間不會(huì)受到父進(jìn)程數(shù)據(jù)變動(dòng)的影響。

流程如下圖所示:

KOOM隨機(jī)采集線上真實(shí)用戶的內(nèi)存鏡像,普通dump和fork子進(jìn)程dump阻塞用戶使用的耗時(shí)如下:

可以看出,基本可以做到無(wú)感知的采集內(nèi)存鏡像。

5.4 KOOM解決hprof文件過(guò)大

Hprof文件通常比較大,分析OOM時(shí)遇到500M以上的hprof文件并不稀奇,文件的大小,與dump成功率、dump速度、上傳成功率負(fù)相關(guān),且大文件額外浪費(fèi)用戶大量的磁盤空間和流量。

因此需要對(duì)hprof進(jìn)行裁剪,只保留分析OOM必須的數(shù)據(jù),另外,裁剪還有數(shù)據(jù)脫敏的好處,只上傳內(nèi)存中類與對(duì)象的組織結(jié)構(gòu),并不上傳真實(shí)的業(yè)務(wù)數(shù)據(jù)(諸如字符串、byte數(shù)組等含有具體數(shù)據(jù)的內(nèi)容),保護(hù)用戶隱私。

裁剪hprof文件涉及到對(duì)hprof文件格式的了解,這里就不綴述了。

5.5 KOOM解決hprof解析的耗時(shí)與OOM

解析hprof文件,對(duì)關(guān)鍵對(duì)象進(jìn)行可達(dá)性分析,得到引用鏈,是解決OOM最核心的一步,之前的監(jiān)控和dump都是為解析做鋪墊。

解析分兩種,一種是上傳hprof文件由server解析,另一種是在客戶端解析后上傳報(bào)告(通常只有幾KB)。

KOOM選擇了端上解析,這樣做有兩個(gè)好處:

節(jié)省用戶流量。

利用用戶閑時(shí)算力,降低server壓力,這樣也符合分布式計(jì)算理念。

這樣就可以把解析過(guò)程拆解成以下兩個(gè)問(wèn)題:

1、哪些對(duì)象需要分析,全部分析性能開銷太大,很難在端上完成,并且問(wèn)題沒(méi)有重點(diǎn)也不利于解決。

2、性能優(yōu)化,作為一個(gè)debug組件,要在不影響用戶體驗(yàn)的情況下完成解析,對(duì)性能有非常高的要求。

5.5.1 關(guān)鍵對(duì)象判定

KOOM只解析關(guān)鍵的對(duì)象,關(guān)鍵對(duì)象分為兩類,一類是根據(jù)規(guī)則可以判斷出對(duì)象已經(jīng)泄露,且持有大量資源的,另外一類是對(duì)象shallow / retained size 超過(guò)閾值。

Activity/fragment泄露判定即為第一種:

對(duì)于強(qiáng)可達(dá)的activity對(duì)象,其mDestroyed值為true時(shí)(onDestroy時(shí)賦值),判定已經(jīng)泄露。

類似的,對(duì)于fragment,當(dāng)mCalled值為true且mFragmentManager為null時(shí),判定已經(jīng)泄露。

Bitmap/window/array/sufacetexture判定為第二種。

檢查bitmap/texture的數(shù)量、寬高、window數(shù)量、array長(zhǎng)度等等是否超過(guò)閾值,再結(jié)合hprof中的相關(guān)業(yè)務(wù)信息,比如屏幕大小,view大小等進(jìn)行判定。

5.5.2 性能優(yōu)化

KOOM在LeakCanary解析引擎shark的基礎(chǔ)上做了一些優(yōu)化,將解析時(shí)間在shark的基礎(chǔ)上優(yōu)化了2倍以上,內(nèi)存峰值控制在100M以內(nèi)。用一張圖總結(jié)解析的流程:

詳細(xì)流程就不在這里綴述了,詳情可見:KOOM解析性能優(yōu)化。

https://juejin.cn/post/6860014199973871624#heading-13

5.6 KOOM使用

KOOM目前已經(jīng)開源,開源地址:

https://github.com/KwaiAppTeam/KOOM

直接參照接入指南接入即可,當(dāng)發(fā)現(xiàn)內(nèi)存超過(guò)閾值或者發(fā)生OOM時(shí),就會(huì)觸發(fā)采集內(nèi)存快照,對(duì)hprof文件進(jìn)行裁剪并分析后得到報(bào)告。

KOOM的報(bào)告是json格式,并且大小在KB級(jí)別,樣式如下所示:

29f2ef1a-43cb-11ec-b939-dac502259ad0.png

大概包括以下信息:

一些可能泄漏的類信息。

泄漏原因,gcRoot,泄漏實(shí)例數(shù)量等。

泄漏對(duì)象的引用鏈,方便定位問(wèn)題。

可見KOOM上傳的數(shù)據(jù)量并不太大,但相對(duì)準(zhǔn)確,非常便于我們分析線上數(shù)據(jù)。

5.7 小結(jié)

本章主要介紹了線上監(jiān)控OOM的開源框架KOOM。

其實(shí)線上監(jiān)控OOM的框架各大廠都有開發(fā),比如美團(tuán)的Probe,字節(jié)的Liko。

https://tech.meituan.com/2019/11/14/crash-oom-probe-practice.html

https://juejin.cn/post/6908517174667804680#heading-7

不過(guò)大部分都沒(méi)有正式開源,只是一些文章介紹原理,有興趣的同學(xué)也可以都了解下。

總結(jié)

對(duì)于優(yōu)化的大方向,我們應(yīng)該優(yōu)先去做見效快的地方,主要有以下幾個(gè)部分:

內(nèi)存泄漏。

內(nèi)存抖動(dòng)。

Bitmap大圖監(jiān)控。

OOM線上監(jiān)控。

我們還介紹了內(nèi)存優(yōu)化的多種實(shí)用工具:

可以使用Profile,MAT在開發(fā)時(shí)定位內(nèi)存抖動(dòng)內(nèi)存泄漏問(wèn)題。

線下開發(fā)、回歸、Monkey、壓測(cè)等環(huán)節(jié)可以自動(dòng)集成LeakCanary檢測(cè)內(nèi)存泄漏;

圖片加載是內(nèi)存優(yōu)化的重點(diǎn),我們可以結(jié)合圖片兜底策略與線上大圖監(jiān)控,優(yōu)化圖片內(nèi)存問(wèn)題。

線上OOM時(shí)通過(guò)KOOM監(jiān)測(cè),內(nèi)存超出閾值時(shí)主動(dòng)dump內(nèi)存快照,通過(guò)上傳分析結(jié)果精準(zhǔn)。分析OOM問(wèn)題。

內(nèi)存優(yōu)化是個(gè)復(fù)雜的過(guò)程,我們?cè)谧鰞?nèi)存優(yōu)化的過(guò)程中,需要結(jié)合多種工具,線上線下結(jié)合,系統(tǒng)化地配合來(lái)定位與解決問(wèn)題。

作者:RicardoMJiang

https://juejin.cn/post/6975876569990447134

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Android
    +關(guān)注

    關(guān)注

    12

    文章

    3980

    瀏覽量

    132631
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3157

    瀏覽量

    75945

原文標(biāo)題:吹爆系列:Android 內(nèi)存還可以這樣優(yōu)化!

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    請(qǐng)問(wèn)如何優(yōu)化OpenVINO?工具套件中的內(nèi)存使用?

    運(yùn)行OpenVINO?推斷時(shí)找不到優(yōu)化內(nèi)存使用情況的方法。
    發(fā)表于 06-25 06:56

    ArkUI-X應(yīng)用工程結(jié)構(gòu)說(shuō)明

    (Ark Byte Code),并分別拷貝到Android和iOS應(yīng)用工程,作為平臺(tái)應(yīng)用資源進(jìn)行管理。 ArkUI應(yīng)用資源 ArkUI Resources資源也通過(guò)OpenHarmony SDK工具
    發(fā)表于 06-19 23:11

    HarmonyOS優(yōu)化應(yīng)用內(nèi)存占用問(wèn)題性能優(yōu)化

    一、使用purgeable優(yōu)化C++內(nèi)存 Purgeable Memory是HarmonyOS中native層常用內(nèi)存管理機(jī)制,可用于圖像處理的Bitmap、流媒體應(yīng)用的一次性數(shù)據(jù)、
    發(fā)表于 05-24 17:20

    HarmonyOS優(yōu)化應(yīng)用內(nèi)存占用問(wèn)題性能優(yōu)化

    應(yīng)用開發(fā)過(guò)程中注重內(nèi)存管理,積極采取措施來(lái)減少內(nèi)存占用,以優(yōu)化應(yīng)用程序的性能和用戶體驗(yàn)。 HarmonyOS提供了一些內(nèi)存管理的工具和接口,
    發(fā)表于 05-21 11:27

    如何高效訓(xùn)練AI模型?這些常用工具你必須知道!

    大模型的發(fā)展同樣面臨瓶頸,訓(xùn)練所需的硬件資源日益增加,比如英偉達(dá)的芯片、電力等(這也可能是ChatGPT5遲遲沒(méi)有出來(lái)的原因)。業(yè)界有觀點(diǎn)認(rèn)為,在大多數(shù)情況下,并不需要全能的大模型,而是更適合專注于特定領(lǐng)域的中小型模型。這類模型針對(duì)垂直領(lǐng)域,性價(jià)比更高,在特定場(chǎng)景下能以較低資源實(shí)現(xiàn)高準(zhǔn)確率的專項(xiàng)任務(wù)。例如在邊緣計(jì)算領(lǐng)域,模型推理所需資源遠(yuǎn)少于訓(xùn)練時(shí)。隨著芯片
    的頭像 發(fā)表于 04-17 16:43 ?2189次閱讀
    如何高效訓(xùn)練AI模型?這些<b class='flag-5'>常用工具</b>你必須知道!

    點(diǎn)焊機(jī)測(cè)量工具選擇與應(yīng)用指南

    和正確使用測(cè)量工具是每個(gè)焊接工程師必須掌握的基本技能之一。本文將詳細(xì)介紹點(diǎn)焊機(jī)測(cè)量工具的選擇原則、常用工具及其具體應(yīng)用方法。 首先,了解點(diǎn)焊機(jī)的工作原理對(duì)于選擇
    的頭像 發(fā)表于 02-19 09:56 ?707次閱讀
    點(diǎn)焊機(jī)測(cè)量<b class='flag-5'>工具</b>選擇與應(yīng)用指南

    hyper 內(nèi)存,Hyper內(nèi)存:如何監(jiān)控與優(yōu)化hyper-v虛擬機(jī)的內(nèi)存使用

    在日常工作中,我們常常需要處理大量的文件和數(shù)據(jù),這些重復(fù)性任務(wù)不僅耗時(shí)耗力,還容易因疲勞而導(dǎo)致錯(cuò)誤。幸運(yùn)的是,批量管理工具的出現(xiàn)為這一問(wèn)題提供了高效的解決方案。今天就為大家介紹Hyper內(nèi)存
    的頭像 發(fā)表于 01-24 14:15 ?1460次閱讀
    hyper <b class='flag-5'>內(nèi)存</b>,Hyper<b class='flag-5'>內(nèi)存</b>:如何監(jiān)控與<b class='flag-5'>優(yōu)化</b>hyper-v虛擬機(jī)的<b class='flag-5'>內(nèi)存</b>使用

    調(diào)試TCP協(xié)議連接的常用工具

    在網(wǎng)絡(luò)通信中,TCP(傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。調(diào)試TCP連接問(wèn)題對(duì)于網(wǎng)絡(luò)工程師和開發(fā)者來(lái)說(shuō)是一項(xiàng)必備技能。 1. 網(wǎng)絡(luò)抓包工具 1.1 Wireshark
    的頭像 發(fā)表于 01-22 09:59 ?4875次閱讀

    Linux Bind DNS服務(wù)解析

    Yum源配置(略),安裝net-tools vim等常用工具。
    的頭像 發(fā)表于 01-20 14:22 ?631次閱讀
    Linux Bind DNS服務(wù)解析

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-mfgtools燒錄流程介紹之燒寫所需鏡像

    USB OTG燒寫所需鏡像在:ELF 1開發(fā)板資料包\\06-常用工具\\06-4 燒寫工具\\OTG燒寫\\mfgtools\\Profiles\\Linux\\OS Firmware
    發(fā)表于 12-21 09:25

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-mfgtools燒錄流程之燒寫方法

    Mfgtools工具是NXP官方提供的用于其系列產(chǎn)品燒寫系統(tǒng)的軟件,可以從官方網(wǎng)站下載,我們的ELF 1開發(fā)資料包中也放了這個(gè)工具,路徑為:ELF 1開發(fā)板資料包\\06-常用工具\\06-4 燒寫
    發(fā)表于 12-20 09:07

    飛凌嵌入式ElfBoard ELF 1板卡-mfgtools燒錄流程介紹之燒寫所需鏡像

    USB OTG燒寫所需鏡像在:ELF 1開發(fā)板資料包\\06-常用工具\\06-4 燒寫工具\\OTG燒寫\\mfgtools\\Profiles\\Linux\\OS Firmware
    發(fā)表于 12-20 09:05

    飛凌嵌入式ElfBoard ELF 1板卡-mfgtools燒錄流程之燒寫方法

    Mfgtools工具是NXP官方提供的用于其系列產(chǎn)品燒寫系統(tǒng)的軟件,可以從官方網(wǎng)站下載,我們的ELF 1開發(fā)資料包中也放了這個(gè)工具,路徑為:ELF 1開發(fā)板資料包\\06-常用工具\\06-4 燒寫
    發(fā)表于 12-19 09:09

    如何優(yōu)化RAM內(nèi)存使用

    優(yōu)化RAM內(nèi)存使用是一個(gè)重要的任務(wù),特別是對(duì)于那些擁有有限內(nèi)存資源的用戶。以下是一些優(yōu)化RAM內(nèi)存使用的策略,這些策略可以幫助您更有效地使用
    的頭像 發(fā)表于 11-11 09:58 ?2246次閱讀

    Kali Linux常用工具介紹

    Kali Linux 虛擬機(jī)中自帶了大量滲透測(cè)試工具,涵蓋了信息收集、漏洞利用、口令破解、漏洞掃描等多個(gè)方面。 以下是按分類簡(jiǎn)要介紹一部分常用工具的使用方法: 使用方法只能當(dāng)做參考,**詳細(xì)
    的頭像 發(fā)表于 11-11 09:29 ?2389次閱讀