參考資料:WWDC2018 iOS Memory Deep Dive
WWDC2018 iOS Memory Deep Dive
iOS內(nèi)存深入研究
盡管這篇文章研究iOS怕享,但涉及的內(nèi)容同樣適用于其他平臺。
- 1.Why reduce memory 為什么減少內(nèi)存
- 2.Memory Footprint
- 3.高級的工具用于分析和研究App的內(nèi)存占用情況
- 4.Images
- 5.在后臺時(shí)候的優(yōu)化
- 6.補(bǔ)充命令:
- 7.總結(jié):
1.Why reduce memory 為什么減少內(nèi)存
減少內(nèi)存占用狱从,系統(tǒng)整體表現(xiàn)更好撤师,app啟動(dòng)更快,后臺駐留時(shí)間更長
2.Memory Footprint
1)Pages:系統(tǒng)分配的內(nèi)存頁
通常16KB
Page types:Clean / Dirty
App的實(shí)際使用內(nèi)存大小 = 頁面數(shù)量 * 頁面大小
2)Memory-mapped files
內(nèi)存映射文件佳励, 是一種在磁盤上的文件,但加載到了內(nèi)存蛆挫,內(nèi)核實(shí)際上是在它們離開磁盤寫入RAM時(shí)進(jìn)行管理的赃承。
3)一個(gè)典型的app內(nèi)存
有一個(gè)dirty、compressed和一個(gè)clean的內(nèi)存段悴侵。
dirty:有app寫入的內(nèi)存瞧剖,所有堆分配內(nèi)存、已解碼的圖像緩沖可免、Frameworks中的__DATA抓于、__DATA_DIRTY段。
Compressed:
iOS沒有傳統(tǒng)的磁盤交換系統(tǒng)浇借, 卻而代之捉撮,它使用內(nèi)存壓縮器memory compressor, 它是在iOS7中引入的妇垢。
內(nèi)存壓縮器memory compressor:壓縮不訪問的頁面巾遭,解壓訪問的頁面
4)Memory warnings內(nèi)存警告
不要想當(dāng)然的認(rèn)為內(nèi)存警告是app造成的,在一個(gè)低內(nèi)存的設(shè)備上闯估,接到一個(gè)電話灼舍,就可能引發(fā)內(nèi)存警告。
內(nèi)存壓縮器是釋放內(nèi)存變得復(fù)雜涨薪,因?yàn)楦鶕?jù)壓縮的內(nèi)容骑素,實(shí)際上你可以比以前使用更多的內(nèi)存。
5)Caching
在CPU和內(nèi)存之間平衡
記住有內(nèi)存壓縮器
使用NSCache而不是NSDictonary尤辱,在內(nèi)存警告的時(shí)候NSCache會(huì)自動(dòng)釋放
6)典型的內(nèi)存分析
主要分析Dirty和compressed:
內(nèi)存限制:
每個(gè)設(shè)備不同 app有一個(gè)相對高的內(nèi)存限制 Extension有一個(gè)低得多的限制
內(nèi)存超過限制的異常:
3.高級的工具用于分析和研究App的內(nèi)存占用情況
1)Xcode內(nèi)存測量計(jì)
2)Instruments
Allocations 分析由你的app所分配的堆
Leaks 檢查一個(gè)進(jìn)程中的內(nèi)存泄漏
VM Tracker 為臟內(nèi)存以及交互內(nèi)存即iOS中的壓縮內(nèi)存分別提供了獨(dú)立的追蹤砂豌,并且告訴你關(guān)于常駐大小的信息厢岂。
常駐內(nèi)存、臟內(nèi)存阳距、干凈內(nèi)存關(guān)系:
https://stackoverflow.com/questions/13437365/what-is-resident-and-dirty-memory-of-ios
Virtual Memory trace 虛擬內(nèi)存追蹤:對與app相關(guān)的虛擬內(nèi)存系統(tǒng)的性能進(jìn)行深入的了解塔粒,它提供了虛擬內(nèi)存系統(tǒng)文件。
3)Memory debugger
使用memgraph文件格式存儲(chǔ)有關(guān)App的內(nèi)存使用信息
? 導(dǎo)出內(nèi)存圖? 搭配命令行工具使用memgraph
第一個(gè)工具:vmmap 通過輸出分配給進(jìn)程的虛擬內(nèi)存區(qū)域筐摘, 它給你的App提供了內(nèi)存消耗的高級分析卒茬, summary參數(shù)是一個(gè)很好的起點(diǎn),它可以打印出很多細(xì)節(jié)咖熟,比如該區(qū)域內(nèi)存大小
顯示進(jìn)程中分配的虛擬內(nèi)存區(qū)
vmmap App.memgraph
Mmap —summary App.memgraph
檢查臟頁面是否有一部分是由鏈接的框架或庫造成的
vmmap -pages App.memgraph | grep '.dylib' | awk '{sum += $6} END { print "Total Dirty Pages:" sum} '
第二個(gè)工具 leaks 在運(yùn)行時(shí)跟蹤堆中的沒有根的對象
leaks App.memgraph
第三個(gè)工具 heap 提供了關(guān)于進(jìn)程堆中對象分配的各種信息圃酵,它可以幫助你追蹤非常復(fù)雜的分配
heap App.memgraphheap App.memgraph -sortBySize
heap App.memgraph -addresses all | <classes-pattern>
heap App.memgraph -addresse NSConcreteData
第四個(gè)工具:malloc_history
malloc_history -callTree App.memgraph address
4)工具的選擇:
4.Images
1) 圖片是內(nèi)存中的大對象。
圖片的大小決定內(nèi)存馍管,不是文件的大小郭赐。
如圖片大小2048 px * 1536 px, 圖片文件大小為590KB
,放到內(nèi)存中圖片所占內(nèi)存大腥贩小:2048 pixels x 1536 pixels x 4 bytes per pixel 約等于 10M
2) 圖片為什么占用這么大的內(nèi)存:
Load階段捌锭,將文件加載進(jìn)內(nèi)存
Decode階段,將圖片解壓縮
Render階段罗捎,顯示圖片
3) 圖片渲染格式:
每像素1字節(jié)-8字節(jié)的格式观谦,應(yīng)該選擇哪種格式?
不用自己選擇格式桨菜,讓代碼選擇格式:
停止使用UIGraphicsBeginImageContextWithOptions 豁状, 每個(gè)像素4個(gè)自己
開始使用UIGraphicsImageRenderer , iOS 10引入倒得, iOS 12中自動(dòng)為你選擇最好的圖像格式泻红。
使用UIGraphicsImageRenderer的方式節(jié)約75%的內(nèi)存。
4) 我們通常對圖像做的另一件事是對它們進(jìn)行下采樣霞掺。
我們不應(yīng)該用UIImage進(jìn)行縮小承桥,如果我們用UIImage繪圖,由于內(nèi)部坐標(biāo)空間變換根悼,這種方法性能并不高,它也會(huì)解壓縮內(nèi)存中的整個(gè)圖像蜀撑。
取而代之挤巡,我們可以使用ImageIO框架,使用streaming API酷麦,只會(huì)生成結(jié)果尺寸大小的圖像矿卑,能節(jié)省內(nèi)存峰值。
這種方法將有一個(gè)內(nèi)存峰值沃饶。
使用ImageIO采用快50%
5.在后臺時(shí)候的優(yōu)化
卸載看不到的大資源
兩種方式:
App生命周期
iewController生命周期
6.補(bǔ)充命令:
vmmap —verbose app.memgraph | grep “str”
引用該地址的對象產(chǎn)生堆棧
leaks —trackTree 地址
malloc_history app.memgraph —fullStacks 地址
7.總結(jié):
1)內(nèi)存有限且是是共用資源
2)在Xcode里運(yùn)行的時(shí)候監(jiān)視內(nèi)存使用
3)讓IOS選擇圖片格式
4)使用ImageIO下采樣圖片
5)卸載不載屏幕上的大資源
6)使用memory graphs深入理解內(nèi)存和減少內(nèi)存