N久沒維護這個博客了,從開始接觸編程到如今已經三四年了。不太習慣寫博客,這應該是個很差的習慣。因此從哪哪天開始,我得改變本身 (: .算法
文采不太好,所以不少的文章都會借鑑他人的,可是我必定會註明是轉載,畢竟如今產權抓的重啊...
編程
0. 概述框架
內存,簡單來講就是內部存儲,複雜來講要從馮·諾依曼計算機結構提及。馮·諾依曼結構,也稱作普林斯頓結構,目前和哈佛結構相對,指出了計算機由運算器、控制器、存儲器、輸入和輸出設備幾大部件組成。現在咱們我的用的機器估計都是這個套路,並且運算器和控制器都合在一塊兒,就是CPU,中央處理器。那麼內存就是CPU能直接讀寫訪問數據的地方(寄存器是在CPU內的,不算哈),有些朋友說誰誰誰的iPhone內存16G、64G,我只能說這個理解方法僅限於存儲部件放在手機裏(內)了,嚴格來說這算「外存」,咱們要討論的不是這個。ide
馮·諾依曼結構還說了,內存是用來存啥的呢?指令+數據!(哈佛的恐怕就不同了)對於咱們開發者來講,指令基本就是代碼邏輯,至於數據麼變量常量確定都算是的了。函數
內存有多大?不大,現今主流的我的機器也就幾G的樣子。iPhone? 通通1G。佈局
咱們操做系統都是運行在內存之上的,1G好像不算大,因此爲了支持多進程,也爲了支持大程序,抽象的虛擬存儲的概念誕生了。性能
簡要的概念先陳述到這,下面詳細說。哦,對了,ARC和MRR我仍是得提一下,這個要是真不知道還真的本身先去了解一下去。優化
1. 通用內存基本原理ui
說iOS的內存,有必要先看看通常的計算機都是怎麼幹的,iPhone也是計算機,通用的道理同樣要遵循。這裏提兩方面:虛存的概念,內存內容的大體分佈。操作系統
虛擬存儲系統。剛剛提到了,物理內存就那麼大點,可是還要跑多個程序,還要接受消耗很大內存的程序,這怎麼辦?涼拌。搞計算機的人都是很聰明的,在操做系統層面作了物理地址和邏輯地址之間的映射轉換,固然處理器硬件上也作了支持。一個程序在運行時,實際要用到的指令和數據都是頗有限的,不可能從頭至尾同時用。那麼對於一個程序來講,僞裝本身有很是大的空間,實際上只要有條理的把暫時要用到的部分放進物理內存供CPU訪問就好,這樣第二個問題解決了。那既然每一個程序(進程)只用一小塊,那整個物理內存就能夠分給多個程序(進程)用了,第一個問題也迎刃而解。固然,這樣作的前提是,數據和指令的動態進出,用完了的暫時不用的踢出內存,須要用的及時加載進來。這個具體的實現方式就多種多樣了,不少實現方式是在外存中開了個交換區供換入換出,但iOS可略有不一樣。
內存的大體分佈。不久之前,我發了一篇文章整理了Mach-O文件的格式分析,裏面很複雜地放了好多東西,包括咱們Build打包時的代碼和數據。而Mach-O文件正是咱們開發內容的一個靜態展示形式,要想在運行的時候看樣子,就得看這文件裏包含的東西是怎麼放進內存的。Objective-C是基於C的,不放看下C程序進程的內存分佈:
最簡單來講分爲兩大部分:指令+數據。再細分一點,五部分:代碼(指令),初始化數據區,未初始化數據區,堆,棧。
其實,這個內存中的佈局方式大部分操做系統中的大部分進程都是相似的。Objective-C的程序包對運行時有着複雜的支持和內容劃分,但也都是在這個大的框架下進行的。
2. iOS的內存管理
其實,iOS的內存管理和其它操做系統大同小異。這裏按照蘋果文檔所述,重點對堆內存分配整理下。
iOS的內存管理分爲幾個層面,從系統到libmalloc,ARC環境下,編譯器也會幫助開發者作「力所能及」的優化處理。
首先,iOS和其它系統同樣,操做系統內核會作虛擬存儲到物理內存的映射管理,並作內存分頁,每頁4K。多個頁構成一個內存區塊統一管理,負責管理的對象是VM object,其中包含了pager、size、resident pages等諸多屬性。全部的內存分配最終都將交由系統來處理(好比vm_allocate/mach_vm_allocate)。
而開發中,在系統內核的基礎上,iOS使用libmalloc。不論是Objective-C的[NSObject alloc],仍是C代碼的對內存分配,重任都會落到malloc庫上,釋放也是如此,最終都將使用malloc庫中的free()。malloc庫中有不少malloc的同族函數能夠動態分配內存。malloc庫中定義了zone的概念,並實現了不一樣的zone(如nano zone和scalable zone),並根據內存需求的大小使用不通算法對nano、tiny、small、large量級的內存進行分配和釋放管理。默認狀況,在第一次調用malloc時,系統會生成一個default zone,後續的默認分配在此進行。好比,malloc_zone_xxx()函數最終都對特定的zone進行分配操做,執行zone->xxx()。每一個zone都以鏈表的形式對已分配過的內存作cache處理,避免頻繁對內核系統發起申請。malloc的內部實現都是開源的,感興趣的能夠去了解去看。
最後強調一下iOS特別須要注意的點:
當前的主流iPhone實際物理內存都不超過1G,能夠說不算大。不過和Android機比起來,我不得不爲蘋果的設計稱讚,1G空間利用得如此高效,性能不差,也控制了發熱。
那麼在這僅有的1G內存中,iOS的操做系統更是拋棄了沒必要要的複雜——系統層面不支持App內存頁換出。當內存吃緊時,對於能夠從新載入的只讀數據來講,直接清理掉,而對於可寫的數據,只能經過App本身去管理維護。內存緊張時,iOS會向App發起memory warning,不配合釋放足夠內存者,殺!
關於Instruments及內存調試,會在後續文章詳細整理出來。