虛擬內存簡介
什么是VM Regions呢?要知道這個首先要了解什么是虛擬內存。當我們向系統申請內存時,系統并不會給你返回物理內存的地址,而是給你一個虛擬內存地址。每個進程都擁有相同大小的虛擬地址空間,對于32位的進程,可以擁有4GB的虛擬內存,64位進程則更多,可達18EB。只有我們開始使用申請到的虛擬內存時,系統才會將虛擬地址映射到物理地址上,從而讓程序使用真實的物理內存。
內存分頁
系統會對虛擬內存和物理內存進行分頁,虛擬內存到物理內存的映射都是以頁為最小粒度的。在OSX和早期的iOS系統中,物理和虛擬內存都按照4KB的大小進行分頁。iOS近期的系統中,基于A7和A8處理器的系統,物理內存按照4KB分頁,虛擬內存按照16KB分頁。基于A9處理器的系統,物理和虛擬內存都是以16KB進行分頁。系統將內存頁分為三種狀態。
活躍內存頁(active pages)- 這種內存頁已經被映射到物理內存中,而且近期被訪問過,處于活躍狀態。
非活躍內存頁(inactive pages)- 這種內存頁已經被映射到物理內存中,但是近期沒有被訪問過。
可用的內存頁(free pages)- 沒有關聯到虛擬內存頁的物理內存頁集合。
當可用的內存頁降低到一定的閥值時,系統就會采取低內存應對措施,在OSX中,系統會將非活躍內存頁交換到硬盤上,而在iOS中,則會觸發Memory Warning,如果你的App沒有處理低內存警告并且還在后臺占用太多內存,則有可能被殺掉。
VM Region
為了更好的管理內存頁,系統將一組連續的內存頁關聯到一個VMObject上,VMObject主要包含下面的屬性。
Resident pages - 已經被映射到物理內存的虛擬內存頁列表
Size - 所有內存頁所占區域的大小
Pager - 用來處理內存頁在硬盤和物理內存中交換問題
Attributes - 這塊內存區域的屬性,比如讀寫的權限控制
Shadow - 用作(copy-on-write)寫時拷貝的優化
Copy - 用作(copy-on-write)寫時拷貝的優化
我們在Instruments的Anonymous VM里看到的每條記錄都是一個VMObject或者也可以稱之為VM Region
堆(heap)和 VM Region
Instruments中有一個VM Track模版,可以幫助我們清楚的了解heap和VM Region的關系
運行Profile,選擇Allocation模版,進入后再添加VM Track模版
下面是我自己寫的一個測試用的工程,選擇Regions Map選項可以看到內存分配的詳細信息
我們在VM Track中可以看到,一個VM Region有4種size。
Dirty Size
Swapped Size
Resident Size
Virtual Size
Virtual Size顧名思義,就是虛擬內存大小,將一個VM Region的結束地址減去起始地址就是這個值。Resident Size指的是實際使用物理內存的大小。Swapped Size則是交換到硬盤上的大小,僅OSX可用。Dirty Size根據官方的解釋我的理解是如果一個內存頁想要被復用,必須將內容寫到硬盤上的話,這個內存頁就是Dirty的。下面是官方對Dirty Size的解釋。secondary storage可以理解為硬盤。
The amount of memory currently being used that must be written to secondary storage before being reused.
所以一般來說app運行過程中在堆上動態分配的內存頁都是Dirty的,加載動態庫或者文件內存映射產生的內存頁則是非Dirty的
點擊Address Range列的箭頭可以看到更詳細的內容,這里進入的是SMALL類型的
總的來說,堆區會被劃分成很多不同的VM Region,不同類型的內存分配根據需求進入不同的VM Region。除了MALLOC_LARGE和MALLOC_SMALL外,還有MALLOC_TINY, MALLOC metadata等等
VM Tracker列屬性解析
% of Res, 當前Type的VM Regions總Resident Size占比
Type,VM Regions的Type,All和Dirty算是統計性質的Type,__TEXT表示代碼段的內存映射,__DATA表示數據段的內存映射。MALLOC_TINY,MALLOC_LARGE,CG Image等Type可以從VM Region的Extend Info中讀取出來
# Regs,當前Type的VM Region總數
Path,VM Region是從哪個文件映射過來,因為有些類似于__DATA和mapped file的內存塊是從文件直接映射過來的。
Resident Size,使用的物理內存量。
Dirty Size,使用中的物理內存塊如果不交換到硬盤保存狀態就不能復用,那么就是Dirty的內存塊,比如你主動malloc出來的內存塊,如果不保留其中的狀態就把它給別人用,那你肯定就無法恢復這個內存塊的信息,所以它是Dirty的。如果是一個映射到內存的文件,就算使用它的內存塊,還是可以重新從磁盤載入文件到內存的,所以是非Dirty的,比如最上面圖中的mapped file那一行,你可以看到Dirty Size是0。
Swapped Size, 在OSX中,不活躍的內存頁可以被交換到硬盤,這是被交換的大小。在iOS中,只有非Dirty的內存頁可以被交換,或者說是被卸載。
Virtual Size,VM Regions所占虛擬內存的大小
Res. %,Resident Size在Virtual Size中的占比
參考:
http://www.lxweimin.com/p/553f34b03624
http://www.lxweimin.com/p/f82e2b378455
https://developer.apple.com/library/archive/documentation/Performance/Conceptual/ManagingMemory/Articles/AboutMemory.html