老司機高德納曾經(jīng)說過:程序開發(fā)人員為提升程序效率在錯誤的方向和時間點浪費了太多的時間移必,過早優(yōu)化是編程領域的萬惡之源
1.內(nèi)存優(yōu)化
一個應用中內(nèi)存消耗分成兩個部分:一個是棧空間一個是堆空間。
椂梗空間:每一個線程都會對應一個專用的棧空間幻件,棧空間可以在線程存在期間使用蛔溃,但是有最大棧空間限制篱蝇。如果超出這個限制贺待,將會導致棧移除,程序被殺死零截。
以下幾種情況麸塞,都是由于棧空間溢出涧衙,導致程序被殺死:
- 可以被遞歸調(diào)用的最大方法數(shù)目哪工。因為每一個方法都會對應一個棧幀奥此,棧幀會消耗一定字節(jié)的內(nèi)存。(這就是為什么雁比,循環(huán)調(diào)用一定會崩潰稚虎,因為函數(shù)棧幀消耗的字節(jié)數(shù)太多,導致內(nèi)存溢出)
- 方法中定義的變量個數(shù)太多偎捎。當然這只是一個理論上可能會導致棧溢出的情況蠢终,實際開發(fā)中基本不會因為定義過多變量被系統(tǒng)kill掉
- 視圖的層級太深。遞歸的調(diào)用layoutSubviews方法跟drawRect方法茴她。
堆空間:每一個進城的所有線程都是會對應同一個堆空間寻拂。堆空間是系統(tǒng)分配的。通過類創(chuàng)建的對象相關的所有數(shù)據(jù)都是放在堆中的丈牢。所以重量級model在系統(tǒng)收到didReceiveMemoryWarning的時候進行清空祭钉,然后在必要的時候重新賦值對于系統(tǒng)優(yōu)化是非常必要的。
內(nèi)存管理的原則
- 你可以擁有你自己創(chuàng)建的對象己沛,比如 new,alloc,copy,mutablecopy
- 你可以使用MRC中的retain 或者是ARC中的_Strong來標示對一個對象的強引用
- 在MRC中當不需要一個對象的時候慌核,需要使用release方法來釋放對象的持有關系,ARC中不需要做任何操作
避免循環(huán)引用引發(fā)的內(nèi)存泄漏
1.delegate weak修飾
2.__weak 修飾被block捕獲的局部變量
3.NSTimer泛粹,對象持有定時器遂铡,定時器也持有對象。解決方法1.自定義清理時機晶姊,可以退出控制器時扒接,也可以點擊某一個按鈕時。
2.能耗
基本沒什么好說的们衙,無關緊要
3.多線程
記准卣:主線程用來更新UI,自線程用來做讀寫文件等比較耗時的操作
每個線程大概會消耗1KB的內(nèi)核內(nèi)存空間蒙挑。主線程會占用1MB的椬谡欤空間,子線程會占用512KB的椧涫矗空間矾利。
多線程的弊端:
- 上下文切換,耗費時間
- 創(chuàng)建耗費時間馋袜,一般一條線程創(chuàng)建之后啟動大概耗費29毫秒
三種多線程的比較
1.GCD - 抽象程度高
- 兩種隊列開箱即用:main和global
- 可以創(chuàng)建更多的隊列
- 硬性要求少于64個線程
2.NSOperationQueue
- 無默認隊列
- 應用管理自己創(chuàng)建的隊列
- 隊列是優(yōu)先級的隊列
- 操作可以有不同的優(yōu)先級
- 使用cancel可以取消操作
- 可以等待某個操作執(zhí)行完成
屬性默認實用的是atomic男旗,但是這樣做屬性也不一定是線程安全的。如果需要做線程安全操作欣鳖,更好的是用鎖察皇。所以不要將屬性設置為atomic。
注意:@synchronized指令會拖慢應用的運行速度泽台,因為在任何時間內(nèi)都只有一個線程在臨界區(qū)什荣。
以下是三種比較常用的鎖
1.NSLock
這是一種低級別的鎖矾缓,一旦獲得了鎖,那么將會執(zhí)行臨界區(qū)中的內(nèi)容稻爬,并且不會超過一個線程執(zhí)行嗜闻。釋放鎖則標志著臨界區(qū)結(jié)束。有個注意點就是 釋放鎖的操作一定要跟加鎖操作在同一線程因篇。
2.NSRecursiveLock
在調(diào)用lock之前泞辐,NSLock必須先調(diào)用unlock。但是正如名字暗示的那樣竞滓,NSRecursiveLock允許在被解鎖之前鎖定多次咐吼。只要解鎖的次數(shù)跟鎖定的次數(shù)相匹配,那么鎖就可以釋放商佑。
上圖是各種鎖的性能锯茄。附上老司機的關于iOS中鎖問題研究文章鏈接:https://bestswifter.com/ios-lock/
4.應用的首次啟動時間
應用首次啟動往往會做很多事情,包括
1.加載默認項
2.檢查測試版本
3.初始化應用標識符
4.初始化崩潰報告
5.建立分析方法
6.建立UI基礎框架
7.建立內(nèi)存緩存
附上 今日頭條開機啟動優(yōu)化的文章:http://www.cocoachina.com/ios/20170208/18651.html
5.UI層面的優(yōu)化
記住下面幾個原則
- 盡量減少主線程中的工作
- 避免視圖層級中的多層嵌套
- 盡可能的延遲視圖的加載茶没,也就是常說的懶加載肌幽。并且對于可以重用的視圖,進行復用 https://github.com/facebookarchive/AsyncDisplayKit
- UIImageView 注意分場景下使用imageNamed跟imageWithContentsofFile抓半。使用圖片與imageView大家接近喂急,避免imageview對圖片縮放操作。
- UITableView的優(yōu)化:http://www.reibang.com/p/4780b10dae55
- 慎用自動布局笛求。自動布局在視圖比較多的時候非常耗費CPU性能廊移。如果頁面元素太多,建議使用原生的frame布局探入,對于提升幀率有非常大的幫助狡孔。當然了marsory對于計算布局有非常大的幫助,往往很復雜的約束蜂嗽,frame要寫一大堆代碼苗膝,但是marsory就可以寫幾行就可以了。根據(jù)業(yè)務不同植旧,可以自己做選擇辱揭。