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
CFAbsoluteTime StartTime; int main(int argc, char **argv) { StartTime = CFAbsoluteTimeGetCurrent(); // ... } - (void)applicationDidFinishLaunching:(UIApplication *)app { dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"Launched in %f sec", CFAbsoluteTimeGetCurrent() - StartTime); }); // ... }
- 使用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啟動時間過長,系統會殺掉程序(轉自)
有一天,公司的網路出現的問題,所有的機器都不能訪問外網了。突然我發現一直執行正常的iPad應用在啟動時經過較長時間的等待後就退出了。
第一反應:是不是對網路通訊的處理有問題,導致程式崩潰?那就進入debug跟蹤一下吧。奇怪的是,在debug模式下,儘管啟動時間較長,但仍然能正常執行下去。(啟動時間長的原因是,啟動時需要訪問伺服器,獲取資料,由於網路有問題,時間就長了)
我一度懷疑是不是ios的bug,但我試了很多其他的應用,為什麼其他應用都能正常執行呢?
經過長時間的google,終於對這個問題的產生理解的越來越清楚了。(google是需要技巧的,不合適的關鍵字往往找不到想要的答案,不要放棄,多嘗試,要相信你不是第一個遇到這個問題的人)
原來,啟動時間太長,ios會認為應用不用正常啟動,所以把應用直接給退出了。並不是應用崩潰了。
那為什麼debug時沒有這個問題呢? 參見文件: http://developer.apple.com/library/ios/#qa/qa2009/qa1592.html
如此看來,解決問題的辦法就是儘快的結束啟動過程。網路訪問通過執行緒解決,這樣就不會阻塞主執行緒的運行了。
參見: http://iphone.demay-fr.net/2010/05/don’t-perform-network-reachability-tests-in-applicationdidfinishlaunching/
最後,為什麼網路有問題時通訊時間就很長呢?我已經設定了timeout為20秒,顯然遠遠大於這個時間。原來,建立網路連線前需要做域名解析,但網關出現問題後,DNS解析也不正常了。DNS的超時時間似乎是應用控制不了的。