iOS效能最佳化策略

來源:互聯網
上載者:User

一:效能最佳化策略
效能問題的處理流程

發現/重現問題
利用工具剖析
形成假設
改進代碼和設計
在以上的四個步驟中迴圈反覆,直到問題解決。
效能最佳化的主要策略:

不要做無用功:不要在啟動時花幾百ms來做logging,不要為同樣的資料做多次查詢
試圖重用:對於建立過程昂貴的對象,要重用而不是重新建立
Table View的cell
Date/Number的formatter
Regex
SQLite語句
使用更快的方式設計、編程:選擇正確的集合對象和演算法來進行編程、選擇適合的資料存放區格式(plist、SQLite)、最佳化SQLite查詢語句
事先做最佳化
對於昂貴的計算,要進行事先計算。iCal中的重複事件,是預先計算出來的,並儲存到資料庫中。
事先計算並緩衝一些對象,可能會佔用大量的記憶體。注意不要將這些對象聲明為static並常駐記憶體。
事後做最佳化:非同步載入、懶載入
為伸縮性而做最佳化:當資料有10條、100條、1000條甚至更多的時候,應用程式的效能不應該對應的呈數量級式的增長,否則無法使用。
說起來慚愧,我真的很少遇到效能問題。以前假設中的效能問題,很多是根本不存在的。事前計劃也杜絕了不了效能問題的產生,所以不如暫時忘記它吧。當然對於一些常識性的提高效能的設計,仍然是必須的。

二:iOS應用啟動速度最佳化
很多app的開發人員都不重視app的啟動速度,這對於片段化使用情景的使用者來說,簡直是災難。

iOS應用的啟動速度
應用啟動時,會播放一個放大的動畫。iPhone上是400ms,iPad上是500ms。最理想的啟動速度是,在播放完動畫後,使用者就可以使用。

如果應用啟動過慢,使用者就會放棄使用,甚至永遠都不再回來。拋開代碼不談,如果抱著PC端遊和單機遊戲的思維,在遊戲啟動時強加公司Logo,啟動動畫,並且使用者不可跳過,也會使使用者的成功使用率大大降低。

iOS系統的“看門狗"

為了防止一個應用佔用過多的系統資源,開發iOS的蘋果工程師門設計了一個“看門狗”的機制。在不同的情境下,“看門狗”會監測應用的效能。如果超出了該情境所規定的已耗用時間,“看門狗”就會強制終結這個應用的進程。開發人員們在crashlog裡面,會看到諸如0x8badf00d這樣的錯誤碼(“看門狗”吃了壞的食物,它很不高興)。
情境 “看門狗”逾時時間
啟動 20秒
恢複運行 10秒
懸掛進程 10秒
退出應用 6秒
後台運行 10分鐘
值得注意的是,Xcode在Debug的時候,會禁止“看門狗”。

如何測試啟動時間:
兩種方法:一種使用NSLog,另外一種使用Time Profiler。

使用NSLog
1 CFAbsoluteTime StartTime;
2 int main(int argc, char **argv) {
3 StartTime = CFAbsoluteTimeGetCurrent();
4 // ... 5 } 6
7 - (void)applicationDidFinishLaunching:(UIApplication *)app {
8 dispatch_async(dispatch_get_main_queue(), ^{
9
NSLog(@"Launched in %f sec", CFAbsoluteTimeGetCurrent() - StartTime);
10
}); 11 // ... 12 }
使用Time Profiler
Instruments->Time Profiler
Profile你的app
切換到CPU strategy view,找到你的app啟動的第一幀
搜尋-[UIApplication _reportAppLaunchFinished]
找到包含-[UIApplication _reportAppLaunchFinished]的最後一幀,即可計算出啟動時間
iOS App啟動過程

連結並載入Framework和static lib
UIKit初始化
應用程式callback
第一個Core Animation transaction
連結並載入Framework及static lib時需要注意:

每個Framework都會增加啟動時間和佔用的記憶體
不必要的Framework,不要連結
必要的Framework,不要票房為Optional
只在使用在Deployment Target之後發布的Framework時,才使用Optional(比如你的Deployment Target是iOS 3.0,需要連結StoreKit的時候)
避免建立全域的C++對象
初始化UIKit時需要注意:

字型、狀態列、user defaults、main nib會被初始化
保持main nib儘可能的小
User defaults本質上是一個plist檔案,儲存的資料是同時被還原序列化的,不要在user defaults裡面儲存圖片等大資料
應用程式的回調:
application:willFinishLaunchingWithOptions:
恢複應用程式的狀態
application:didFinishLaunchingWithOptions:
我一直認為設計的本質是折衷。當你為了100ms的啟動速度最佳化歡欣不已,而無視那長達10秒的啟動動畫時,應該想想究竟什麼是應該做的。做正確的事情比把事情做好更重要。
三:事件處理-拯救主線程
使用者經常評論app的一個用詞是“卡頓”,很大的因素是因為主線程被佔用了。使用者的事件是在主線程被處理的,包括點擊、滾動、加速計、Proximity Sensor。
為了保證事件的平滑處理,需要進行如下最佳化:

最小化主線程的CPU佔用,將工作“搬離”主線程, 不要阻塞主線程

前面兩篇文章,我們接觸到了Time Profiler。使用它可以剖析不同線程的CPU使用方式,並給出呼叫堆疊的CPU時間佔用百分比。如果app“卡頓”,並且在Time Profiler的結果可以找到明確的高佔用堆棧,你需要把它最佳化掉。

將工作“搬離”主線程 - 隱式並發
為了得到更流暢的互動體驗,iOS已經幫我們做了很多事情,Android就沒有這麼好運了。iOS將以下這些事情搬離了主線程:

View和layer的動畫(動畫繪製前的計算,而不是drawing過程)
Layer的組合計算(drawing後的疊加)
PNG的解碼(是的,你沒看錯;而且利用了CPU的多核心)
注意滾動(Scrolling)不是一個動畫,而是在Main Run Loop中不斷接收事件並且處理。

將工作“搬離”主線程 - 顯式並發
這裡是需要開發人員們搞定的部分。磁碟、網路等I/O會阻塞線程,不要把它們放到主線程裡。常用的技術有:
Grand Central Dispatch(GCD)
NSOperationQueue
NSThread
iOS 4.0後,易用的GCD技術被廣泛使用。例如:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
// do something in background dispatch_async(dispatch_get_main_queue(), ^{
// do something on main thread
}); });
GCD的陷阱
GCD其實就是線程,只不過提供了一個更高層次的抽象。過多的線程一定會帶來效能損失,因此GCD設計了一個最高允許的線程值(對開發人員透明,不用管到底有多少)。那麼如何解決這個問題呢?

將隊列序列化
使用Dispatch sources
使用帶有限制的NSOperationQueue
使用Cocoa Touch提供的非同步方法呼叫
另外一個陷阱是安全執行緒:

UIKit必須要在主線程使用,除了UIGraphics,UIBezierPath,UIImage
大多數CG、CA、Foundation的類,不是安全執行緒的
如果你使用了ojbc runtime來進行introspection,由於它是thread safe的,可能會導致競爭
此外,iOS 4.3添加了DISPATCH_QUEUE_PRIORITY_BACKGROUND,它擁有非常低的優先順序。這個優先順序只用於不太關心完成時間的真正的背景工作,如果要表示較低的優先順序,你通常需要的是DISPATCH_QUEUE_PRIORITY_LOW。
不要阻塞主線程
即使佔用了很少的CPU時間(如果你在Time Profiler中看到這些的資料),也可能會阻塞主線程。磁碟、網路、Lock、dispatch_sync以及向其它進程/線程發送訊息都會阻塞主線 程。Time Profiler只能檢測出佔用CPU過多的堆棧,但檢測不了這些IO的問題。

大多數的阻塞事件,都會伴隨著一個系統調用,如:
read/write - 讀寫檔案
send/recv - 收髮網絡資料
psynch_mutex_wait - 獲得鎖
mach_msg - IPC
System Trace這個Instrumentor,記錄了所有的系統調用,以及每次調用的等待時間。如果你在System Trace裡面發現了CPU Time很低,但Wait Time很高的調用,說明在主線程處理I/O已經嚴重損害了app的效能。

保證主線程的低CPU佔用,將I/O移至其它線程,可以大大地提高主線程對互動事件的處理能力。我建議開發人員朋友們寫代碼的時候,除非是以前遇到過的問題,都沒有必要假設問題存在。80%的最佳化都是不必要的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.