instruments xcode自帶除錯工具 iOS效能優化:Instruments使用實戰
iOS效能優化:Instruments使用實戰
採用Instruments 來分析整個應用程式的效能.發現很多有意思的點,以及效能優化和一些分析效能消耗的技巧,小結如下。
Instruments使用技巧
關於Instruments,當然如果不習慣官方英文可以在這裡找到中文字翻譯版本PDF參閱.Instruments 確實是一個很強大的工具,用它來收集關於一個或多個系統程序的效能和行為的資料極為方便,並能及時跟蹤隨著時間產生的資料.還可以廣泛收集不同型別的資料.關於Instrument工具基本使用不在贅述.如下重點說明一些使用技巧.
1.概覽
工具通過Xcode工具欄中Product->Profile
Instrument概覽[via by chenkai]
當點選Time Profiler應用程式開始執行後.就能獲取到整個應用程式執行消耗時間分佈和百分比.為了保證資料分析在統一使用場景真實行有如下點需要注意:
在開始進行應用程式效能分析的時候,一定要使用真機,模擬器執行在Mac上,然而Mac上的CPU往往比iOS裝置要快。相反,Mac上的GPU和iOS裝置的完全不一樣,模擬器不得已要在軟體層面(CPU)模擬裝置的GPU,這意味著GPU相關的操作在模擬器上執行的更慢,尤其是使用CAEAGLLayer來寫一些OpenGL的程式碼時候. 這就導致模擬器效能資料和使用者真機使用效能資料相去甚運
另外在開始效能分析前另外一件重要的事情是,應用程式執行一定要釋出配置而不是除錯配置.
在釋出環境打包的時候,編譯器會引入一系列提高效能的優化,例如去掉除錯符號或者移除並重新組織程式碼.另iOS引入一種"Watch Dog"[看門狗]機制.不同的場景下,“看門狗”會監測應用的效能。如果超出了該場景所規定的執行時間,“看門狗”就會強制終結這個應用的程序.開發者可以crashlog看到對應的日誌.但Xcode在除錯配置下會禁用"Watch Dog".
下圖為兩種除錯方式,一般來說,我們會用前者除錯CPU的執行狀況
2.Time Profiler
選擇Time Profiler
time profile時間分析工具用來檢測應用CPU的使用情況.可以看到應用程式中各個方法正在消耗CPU時間.使用大量CPU不一定是個問題.類似我們客戶端中不同場景的天氣動畫[類似大雨]的路徑就對CPU依賴就非常高,動畫本身也是非常苛刻且耗費資源較多的任務.
點選Record 開始執行.
Time Profile 分析介面[via by chenkai]
剛開始我們拿到分析資料時往往是這樣的:
效能資料[via by chenkai]
這裡顯示的是執行程式碼完整路徑,其中系統和應用本身一些呼叫路徑完全揉捏在一起.完全看不到我們關心的應用程式中實際程式碼執行耗時和程式碼路徑實際所在位置.簡單的方式可以快速勾選右邊Call Tree中Separate Thread和Hide System Libraries兩個選項[後面會解釋選項作用]:
拆分後效能資料[via by chenkai]
可以看到直接能夠看到應用程式各個方法呼叫耗時直接路徑,剔除掉了系統相關方法和反向呼叫樹路徑.清爽很多.如果覺得這還不夠直觀,選擇任意一個耗時方法分支[這裡選擇WeatherViewController viewDidLoad]雙擊進入會看到:
程式碼&耗時詳情
可以直接定位到viewDidLoad的程式碼,也可以直觀的看到改方法下呼叫其他方法耗時的時間.類似[self loadCityWeatherScroollerView]耗時是121x,x既耗時單位這裡為ms毫秒.當然如果直接在Instrument找到問題覺得不方便修改,可以直接點選右上方Xcode按鈕會直接定位Xcode對應呼叫方法入口.這樣很容易能夠快速定位程式碼佔用CPU最多的方法.也可以開啟Xcode快速修改並重新執行Profile來看修改後耗時前後對比.簡單便捷.
這裡對右側call tree選項有必要做一下說明[官方user guide翻譯]:
Separate By Thread:執行緒分離,只有這樣才能在呼叫路徑中能夠清晰看到佔用CPU最大的執行緒.
Invert Call Tree:從上到下跟蹤堆疊資訊.這個選項可以快捷的看到方法呼叫路徑最深方法佔用CPU耗時,比如FuncA{FunB{FunC}},勾選後堆疊以C->B->A把呼叫層級最深的C顯示最外面.
Hide Missing Symbols:如果dSYM無法找到你的APP或者呼叫系統框架的話,那麼表中將看到呼叫方法名只能看到16進位制的數值,勾選這個選項則可以隱藏這些符號,便於簡化分析資料.
Hide System Libraries:這個就更有用了,勾選後耗時呼叫路徑只會顯示app耗時的程式碼,效能分析普遍我們都比較關係自己程式碼的耗時而不是系統的.基本是必選項.注意有些程式碼耗時也會納入系統層級,可以進行勾選前後前後對執行路徑進行比對會非常有用.
關於其他方法不再贅述.
效能分析&程式碼優化
我們這次效能優化主要針對如下兩個使用場景:
A:應用程式第一次啟動到進入天氣首頁的時間.
B:從後臺切到前臺天氣首頁佔用時間.
在還沒有拿到效能分析資料之前,一直認為第一次啟動耗時主要浪費AppDelegate中第三方框架初始化上[類似WeiBo&WeChat 相關SDK初始化呼叫].當我們拿到實際效能資料耗時佔用比時發現實際情況並非如此:
啟動耗時
如上可以看到應用程式啟動初始化工作主要會在MJAppDelegate如下兩個方法展開:willFinishLaunchingWithOptions和didFinishLaunchingWithOptions,其中第三方框架初始化工作主要是willFinishLaunchingWithOptions中完成的.而實際情況耗時佔比非常小.基本可以忽略不計.
而我們要優化兩個啟動時間場景,不同在於.第一次進入應用需要經過新手教程、新增城市、請求城市資料、解析資料、初始化天氣首頁UI元素並載入場景動畫. 而從後臺進入時則從本地儲存DT檔案中解析天氣資料、初始化天氣首頁UI元素並載入天氣動畫.
1.NSDateFormatter問題凸顯
針對這點重點分析應用啟動&天氣首頁耗時. 在AB兩個場景均發現載入首頁元素髮現如下問題:
NSDate(TimeAgo)getDateStrByTimeZone耗時
繼續跟蹤發現:
NSDate耗時
在AB兩個場景裡均出現載入MJLineChartView 和 TendencyChartView 時獲取時區對應時間上耗時較大.而耗時主要在getDateStrByTimeZone這個方法呼叫上.
其中建立一個NSDateFormatter物件平均耗時33ms左右而設定NSDateFormatter的3個屬性平均耗時也在30ms左右.因為首頁24小時天氣和未來幾天預報中.需要for迴圈中遍歷資料,導致這個方法別重複呼叫多次,則消耗時間不斷疊加.
針對這個問題:
NSDateFormatter物件本身初始化很慢,同樣還有NSCalendar也是如此.然而在一些使用場景中不可避免要使用他們,比如Json資料解析中.使用這個物件同時避免其效能開銷帶來效能開銷,一般比較好的方式是通過新增屬性(推薦)或建立靜態變數保持該物件只被初始化一次,而被多次複用.不得不值得一提的是設定一個NSDateFormatter屬性速度差不多是和建立新的例項物件一樣慢!
針對NSDateFormatter時間開銷出了重用物件外,儘量避免採用其處理多個日期格式.當然針對日期格式處理如果需要提高更多速度,可以直接採用C,可以採用第三方庫來規避這個問題..
2.UIImage快取取捨
UIImage使用
在Main Thread中發現不同動畫場景中Image IO 開銷和耗時所佔比例均不一,在UIImage元素較多總體疊加耗時也會佔用一定比例.記憶體開銷也會明顯增高.
UIImage載入圖片方式一般有兩種:
A:imagedNamed初始化
B:imageWithContentsOfFile初始化
二者不同之處在於,imageNamed預設載入圖片成功後會記憶體中快取圖片,這個方法用一個指定的名字在系統快取中查詢並返回一個圖片物件.如果快取中沒有找到相應的圖片物件,則從指定地方載入圖片然後快取物件,並返回這個圖片物件.而imageWithContentsOfFile則僅只載入圖片,不快取.
大量使用imageNamed方式會在不需要快取的地方額外增加開銷CPU的時間來做這件事.當應用程式需要載入一張比較大的圖片並且使用一次性,那麼其實是沒有必要去快取這個圖片的,用imageWithContentsOfFile是最為經濟的方式,這樣不會因為UIImage元素較多情況下,CPU會被逐個分散在不必要快取上浪費過多時間.
使用場景需要程式設計時,應該根據實際應用場景加以區分,UIimage雖小,但使用元素較多問題會有所凸顯.
3.天氣首頁載入策略
在AB兩種場景把效能資料對比分析發現:
天氣首頁WeatherView初始化耗時一直300ms-450ms之間,佔據首頁耗時很大一部分.且一直固定的開銷.佔據Main Thread3分之一.
而使用者進入最先看到是天氣首頁上半部分:
而下半部分需要滾動才能看到下半部分.且不一定觸發:
而現在整個首頁View的初始化和更新全部放到主執行緒來做.其中WeatherInfoView updateAllInfo方法更新耗時最長.更多的view意味著更多的渲染,也就是意味更多的CPU和記憶體消耗,對於我們天氣首頁在UIScrollView裡邊嵌套了很多view更是如此。
而針對這種情況不要在主執行緒承載過多的操作.uikit渲染,使用者輸入迴應都需要主程序上完成.主執行緒被意外block或者載入響應耗時過多都會影響到使用者體驗.而針對資源消耗過大操作,處理原則是最小化主執行緒的CPU佔用,將工作“搬離”主執行緒,不要阻塞主執行緒.類似本地一些IO完全移到其他執行緒來做.
除錯time profiler過程中發現,即使佔用了很少的CPU時間(如果你在Time Profiler中看到這些的資料),也可能會阻塞主執行緒。磁碟、網路、Lock、dispatch_sync以及向其它程序/執行緒傳送訊息都會阻塞主線程。Time Profiler只能檢測出佔用CPU過多的堆疊,但檢測不了這些IO的問題.很奇怪.在System Trace裡面突然發現了CPU Time很低,但Wait Time很高的呼叫,說明在主執行緒處理I/O已經嚴重損害了app的效能,這個時候考慮把這個操作優化了.
而針對我們應用首頁ui中多個view,在載入策略完全可以採用多執行緒進行同步載入,只把上半部分放在主執行緒中載入,下班可以同時開一個執行緒進行同步載入.這樣可以大大降低組執行緒初始化和更新時間,當首頁初始化完畢已經呈現是,下半部分其實已經另外一個執行緒處理完畢.
另外針對單個view 儘量不要在viewWillAppear費時的操作,viewWillAppear在 view 顯示之前被呼叫,出於效率考慮,在這個方法中不要處理複雜費時的事情;只應該在這個方法設定 view 的顯示屬性之類的簡單事情,比如背景色,字型等。不然,使用者會明顯感覺到 view 顯示遲鈍.
4:應用首次載入時間
應用首次啟動載入操作:
首次載入坐了如下操作:
A: 連結和載入:可以在Time Profile中顯示dyld載入庫函式,庫會被對映到地址空間,同時完成繫結以及靜態初始化.
B: UIKit初始化:如果應用的Root View Controller是由XIB實現的,也會在啟動時被初始化.
C: 應用回撥:呼叫UIApplicationDeleagte的回撥:application:didFinishLaunchingWithOptions.
D: 第一次Core Animation呼叫:在啟動後的方法-[UIApplication _resportAppLaunchFinished]中呼叫CA::Transaction::commit實現第一幀畫面的繪製.
應用程式首次載入中啟動方法willFinishLaunchingWithOptions和didFinishLaunchingWithOptions只做應用程式首次啟動必須的要操作,而針對_dyid_start在初始化庫framework函式的操作.不必要的Framework不要連結,避免首次載入耗時.
小結如上.很多地方程式碼呼叫和底層機制看的不是特別明白,整理總結關於優化部分實在有限,如上僅供各位參考.另外Instruments確實是把分析程式碼利器.目前沒有任何一個第三方工具可以去替代.推薦各位使用.
相關推薦
instruments xcode自帶除錯工具 iOS效能優化:Instruments使用實戰
iOS效能優化:Instruments使用實戰 採用Instruments 來分析整個應用程式的效能.發現很多有意思的點,以及效能優化和一些分析效能消耗的技巧,小結如下。 Instruments使用技巧 關於Instruments,當然如果不習慣官方英文可以在這
Xcode自帶除錯命令集
LLDB的Xcode預設的偵錯程式,它與LLVM編譯器一起,帶給我們更豐富的流程控制和資料檢測的除錯功能。平時用Xcode執行程式,實際走的都是LLDB。熟練使用LLDB,可以讓你debug事半功倍 LLDB基礎知識 LLDB控制檯 Xc
Xcode自帶工具symbolicatecrash解析iOS Crash檔案
一、找到.app檔案和.app.dSYM檔案 在桌面建立一個crash資料夾,然後Xcode->Window->Organizer找到Archives找到App->右擊Show in Finder 複製.app和.app.dSYM到crash夾檔案:右擊.xc
Xcode自帶工具 FileMerge 進行檔案比較、合併
FileMerge 是XCode自帶的一款工具,可進行程式碼比較、合併。 1、在應用程式中找到Xcode右鍵選擇顯示包內容,路徑如下圖,可複製快捷鍵方便使用。 也可以直接開啟Xcode,在Open Developer Tool中開啟,如下圖。 如下圖: 2、開啟FileMerge,如下圖,選擇左右
Xcode自帶的檢視檢視佈局的工具
開始試著用reveal,但是reveal需要修改一些東西,並且還收費(通過修改系統時間什麼的太麻煩了)。最近了解到Xcode自己就帶有檢視檢視的工具,雖然沒有reveal那麼強大,但是可以看出控制元件
iOS Xcode自帶Git入門及程式碼提交GitHub
首先,Git不是github,Git和github的關係就像是 英雄聯盟和對戰遊戲平臺 其次,Xcode內建了Git,我們可以利用github或者國內的開源中國進行程式碼託管,直接在Xcode上進行團隊協作 客戶端(pc/mac)想要和github(碼雲等
死鎖排查的小竅門 --使用jdk自帶管理工具jstack
pre ble new deadlock 一段 指令 tro bject print 本文版權歸 遠方的風lyh和博客園共有,歡迎轉載,但須保留此段聲明,並給出原文鏈接,謝謝合作。 開發時間久了,難免會寫出一些一些死鎖的代碼,自己明明調用該方法可該方法就是不執行、不進該
安裝好SQL Server 2016,沒有自帶SSMS 工具
sqlhttps://docs.microsoft.com/zh-cn/sql/ssms/sql-server-management-studio-changelog-ssms?view=sql-server-2016#previous-ssms-releases 安裝:SQL Server Manageme
使用QT自帶打包工具windeployqt.exe打包程式
步驟: 1、新建一個資料夾,隨意取名Release 2、放入編譯好的應用程式,以QConfigure.exe為例 3、在Qt安裝目錄D:\Qt\32\Qt5.5.1\5.5\msvc2013\bin下找到windeployqt.exe,將windeployqt.exe放到Release資
windows自帶管理工具(exe/cpl/msc)
exe類 英文 中文 英文 中文 notepad 記事本 calc 計算器 control 控
QT如何自定義滑鼠樣式及如何用windows自帶畫圖工具進行滑鼠樣式的設計
眾所周知,QT系統自身擁有眾多的滑鼠樣式,這些滑鼠樣式均比較常見,顏色、樣式為系統所固有,無法更改。哪麼能不能自定義滑鼠的形狀、顏色等特點呢?答案是可以的。自定義的滑鼠樣式可以隨意指定,顏色更是多種多樣,極具個性化。 QT自帶的滑鼠樣式(在此不做過多介紹): 可以直接拿來用,具體用法如下:
nmap埠檢測命令總結&kali自帶wafw00f工具
使用nmap目的是為了檢測目標機開放的埠情況。 一、檢測埠情況 第一步:檢測目標機是否開啟(nmap -sn * 命令) 第二步:檢測目標機開放的埠,分別向1000個TCP埠傳送探測包,若有迴應則說明埠是開放的,也就說明對應服務是執行狀態。(nmap -O * 命令) 第
分析802.11無線報文hexdump內容:利用wireshark自帶二進位制工具text2pcap將hexdump內容轉換為pcap檔案
除錯wifi驅動,有時會將報文內容以16進位制形式打印出來,如下是一個beacon報文的內容: 0000 80 00 00 00 ff ff ff ff ff ff 40 e3 d6 cb fe d0 0010 40 e3 d6 cb fe d0 70 29 7b 00 55 41 00 00 00
Visual Studio自帶WSDL工具生成WebService服務類
WebService有兩種使用方式,一種是直接通過新增服務引用,另一種則是通過WSDL生成。 新增服務引用大家基本都用過,這裡就不講解了。 那麼,既然有直接引用的方式,為什麼還要通過WSDL生成呢? 因為通過WSDL生成,就只有一個.cs 檔案,便於管理,更簡潔。 一、
Java自帶常用工具
1.jps–列出java程序,類似於ps命令–引數-q可以指定jps只輸出程序ID ,不輸出類的短名稱–引數-m可以用於輸出傳遞給Java程序(主函式)的引數–引數-l可以用於輸出主函式的完整路徑–引數-v可以顯示傳遞給JVM的引數2.jinfo檢視JVM引數修改簡單的引數3
windows自帶diskpart工具的使用(檢視磁碟,檢視 建立 轉換磁碟分割槽)
1、進入命令列視窗 2、輸入diskpart命令後按回車鍵,進入DISKPART工具 3、輸入list disk命令後按回車鍵,檢視電腦當前可用硬碟,編號為0、1、2……如果你只有一塊硬碟,則只有0號磁碟;有兩塊硬碟,則還會顯示1號磁碟,以此類推 4、輸入
利用caffe中自帶的工具來視覺化loss 和accuracy
以前只是一股腦的訓練,卻很少注意到這些,今天仔細研究了下,發現caffe自帶技能包.方法如下:1訓練,和以前略有不同的是,./XX.sh|& tee xx.log,保證在caffe-master目錄下生成日誌檔案,或者去根目錄下的temp中尋找也可以.2在caff
Xcode自帶git將本地專案上傳到GitHub
1.cd到你的專案目錄下 2.git init 3.git add . 4.git commit -m "first commit" 5.git remote add origin https://github.com/icefishlily/audioPlayer_2.git//換成你自己的u
使用eclipse自帶的工具訪問webService
通過圖形化介面的方式呼叫webservice 工具1:webservice explorer url也可以輸入本地檔案的路徑:將檔案的路徑放瀏覽器是執行以下,然後複製瀏覽器地址到WSDL URL即可
使用Eclipse自帶的工具檢測和資料庫連線時否成功
1.第一步 找到 Data Source Explorer 並 new 1.1如果沒有找到 Data Source Explorer 可根據如圖找: 2.第二步 選中自己要連線的資料庫 3.第三步 4.第四步 選中資料庫版本