VM Tracker是Xcode Instruments自帶的一個內存分析工具,能夠幫助你快速查看虛擬內存塊的用量狀態以及根據虛擬內存塊的tag進行分類。若是你想知道關於虛擬內存的相關知識,能夠先閱讀探索iOS內存分配這篇文章,若是你對虛擬內存以及VM Region不太瞭解的話,閱讀下面的內容可能會有些障礙。想要使用VM Tracker,使用Instruments的Allocations模版便可。若是模版自帶的VM Tracker不顯示信息,能夠用右邊的加號再添加一個VM Tracker。html
% 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中的佔比咱們可使用vm_allocate
方法申請一塊虛擬內存。下面是具體代碼。ios
vm_address_t address;
vm_size_t size = 1024 * 1024 * 100;
vm_allocate((vm_map_t)mach_task_self(), &address, size, VM_MAKE_TAG(200) | VM_FLAGS_ANYWHERE);
複製代碼
上面的代碼申請了一塊100M的虛擬內存,(vm_map_t)mach_task_self()
表示在本身的進程空間內申請。size
的單位是byte。 VM_MAKE_TAG(200)
是給你申請的內存塊提供一個Tag標記。我這裏提供了一個200數值做爲標記,後面我會具體介紹這個數值在VM Tracker中的做用。最後咱們用VM Tracker看一下咱們本身分配的虛擬內存塊。 app
你可能會注意到這塊內存塊的Resident Size和Dirty Size都是0KB,由於咱們並無使用這塊內存,因此並無虛擬內存被關聯到物理內存上去。你能夠嘗試使用這塊內存,而後去VM Tracker觀察變化。好比使用下面的方式填充內存塊。ide
for (int i = 0; i < 1024 * 1024 * 100; ++i) {
*((char *)address + i) = 0xab;
}
複製代碼
接下來咱們來介紹內存塊的Type,我曾經思考好久VM Tracker是如何識別出每一個內存塊的Type的。好比MALLOC_TINY,MALLOC_SMALL,ImageIO等等。答案就在vm_allocate
方法的最後一個參數flags。flags能夠分紅2個部分。VM_FLAGS_ANYWHERE
屬於flags裏控制內存分配方式的flag,它表示能夠接受任意位置的內存分配。它的宏定義以下。工具
#define VM_FLAGS_ANYWHERE 0x0001
複製代碼
從定義能夠看出,2個字節就能夠存儲它,int有4個字節,還剩下2個就能夠用來存儲標記內存類型的Type了。蘋果提供了VM_MAKE_TAG
宏幫助咱們快速設置Type。VM_MAKE_TAG
實際上作了一件很簡單的事情,把值左移24個bit,也就是3個字節,因此係統留給了咱們1個字節來表示內存的類型。下面是VM_MAKE_TAG
的宏定義。spa
#define VM_MAKE_TAG(tag) ((tag) << 24)
複製代碼
實際上蘋果已經內置了不少默認的Type,下面列出一部分。rest
#define VM_MEMORY_MALLOC 1
#define VM_MEMORY_MALLOC_SMALL 2
#define VM_MEMORY_MALLOC_LARGE 3
#define VM_MEMORY_MALLOC_HUGE 4
#define VM_MEMORY_SBRK 5// uninteresting -- no one should call
#define VM_MEMORY_REALLOC 6
#define VM_MEMORY_MALLOC_TINY 7
#define VM_MEMORY_MALLOC_LARGE_REUSABLE 8
#define VM_MEMORY_MALLOC_LARGE_REUSED 9
複製代碼
若是咱們使用VM_MEMORY_MALLOC_HUGE
來做爲Type,再用VM Tracker觀察會怎麼樣呢?下面是內存分配的代碼。code
vm_address_t address;
vm_size_t size = 1024 * 1024 * 100;
vm_allocate((vm_map_t)mach_task_self(), &address, size, VM_MAKE_TAG(VM_MEMORY_MALLOC_HUGE) | VM_FLAGS_ANYWHERE);
複製代碼
下面是VM Tracker的截圖。 cdn
很明顯VM Tracker認出了這塊內存,而且將它的Type設定爲MALLOC_HUGE。若是你想使用vm_allocate
來分配和管理大內存,也能夠設置一個Type,方便快速定位到本身的虛擬內存塊。htm
本文主要介紹了VM Tracker中關於虛擬內存的一些概念,以及如何自行分配虛擬內存。瞭解了這些以後,在分析內存暴漲或者泄漏時就有了新的思路,而不單單是侷限於基於malloc內存塊的內存分析了。