1. 程式人生 > >iOS應用啟動速度分析

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的超時時間似乎是應用控制不了的。