隨著用戶的增長,用戶使用時間的延長,APP的內存問題會變得越發嚴重。今年WWDC大會,有個專門的session,深入解析iOS內存。
我是寫了iOS內存分析上-圖片加載內存分析后看到了這個session,發現大致的思路相同,都是從實用角度分析怎么減少內存消耗、footprint測量、圖片內存占用分析幾個角度。session中的講解更加詳盡一些,本文嘗試整理session內容,并會增加一些自己的理解。
一、Why reduce memory
1 為什么要減少內存消耗?
APP加載更快,系統更流暢,APP的內存駐留時間更長,其他APP的內存駐留時間更長……總之,一句話:
為了更好的用戶體驗
2.減小哪一部分的內存消耗?
不是所有的內存都是同等的,我們在iOS開發中,需要關注的內存消耗是:
Memory Footprint
二、Memory Footprint
1.Memory Pages
系統是按頁分配內存的,每個page通常是16KB,APP消耗的內存就是:
Memory in use = Number of pages * Page size
iOS內存可以分為clean memory和dirty memory。當用戶(也就是程序員)申請分配內存時,系統只會對這塊內存進行標記,這時只會分配虛擬內存,而不會分配物理內存,此時內存是clean memory。當對這塊內存進行數據填充時,才會分配物理內存,內存變為dirty memory。
example code:
int *array = malloc(20000 * sizeof(int));
array[0] = 32;
array[19999] = 64;
首先分配了20k的int,需要6個page,分別對page0和page5寫入數據后,這兩個page變為了dirty memory,而page1~4這4個page仍然是clean memory。
2.內存模型
提出了一個內存分級模型
Dirty Memory
Compressed
Clean Memory
Clean Memory
就是可以從內存中換頁出去的內存(can be paged out of Memory)。可以是:Memory-mapped files(image.jpeg, blob.data, training.model), frameworks*(__DATA_CONST)
一些運行時的用法,如swizz,會將以上所說的framework中的clean memory,變為dirty memory
Dirty Memory
是APP寫入的內存。可以是:All heap allocations, decoded image buffers, frameworks
特別指出,由于單例創建后會常駐內存,全局initialize在load或者link后就會運行,可以一定程度上減少dirty memory。
+ (void)load; // Objective-c
+ (void)initialize; // Objective-c
__attribute__((constructor)) // Objective-c
initialize(); // swift
Compressed Memory
iOS系統中沒有磁盤交換系統(disk swap system,就是傳統的PC端的虛擬內存),而是在iOS7開始引入了內存壓縮(Memory compressor)。
它會將未訪問的頁(unaccessed pages)進行壓縮,從而獲得更多的內存空間,并在訪問頁時,進行解壓縮。
3.內存警告
內存警告未必是由于前臺APP導致的。比如,當設備在低內存時,打過來一通電話,就可能會出發內存警告。同時,由于Compressed Memory的存在,內存警告時的策略需要有多重情況的策略設計,避免為了釋放內存而訪問了compressed內存,導致內存使用更加惡劣,最終OOM。
推薦使用NSCache,有系統內存feature的優化。
4.Memory Footprint
有了上面的儲備知識后,可以通過以下公式進行內存優化
Memory Footprint = Dirty Memory + Compressed Memory
也就是通常的APP,不需要關注Clean Memory,使用NSCache進行緩存,也可以不過多關注Compressed Memory。重點關注Dirty Memory。
5.Memory Footprint Limit
Memory Footprint 限制是根據設備變更的,不同的設備的上限不同。
APP 的Memory Footprint Limit上限比較高
Extention的Memory Footprint Limit上限比較低
以及Xcode 10可以捕獲內存超限的事件 EXC_RESOURCE_EXCEPTION。emmm,所以是做了llvm優化,使得能夠進行相關事件的捕獲?期待iOS12發布,Xcode10打包,之后就可以順理成章拋棄iOS8,迎接新特性,走向人生巔峰了。