蘇寧蛙測基于Instruments檢測iOS性能技術(shù)
原創(chuàng)【51CTO.com原創(chuàng)稿件】1.背景
在蘇寧智慧零售的戰(zhàn)略中,移動應(yīng)用占據(jù)重要位置,線上應(yīng)用的用戶體驗(yàn)對于產(chǎn)品推廣有直接影響,而作為移動兩大重要陣營之一的iOS系統(tǒng),應(yīng)用上架前的性能指標(biāo)顯得尤為重要。在不嵌入代碼的前提下,蛙測平臺需要獲得應(yīng)用運(yùn)行時的內(nèi)存、CPU、FPS、冷啟動時間、熱啟動時間等數(shù)據(jù),提供給開發(fā)部門,進(jìn)行上線前優(yōu)化。
蘇寧現(xiàn)有的iOS應(yīng)用性能測試數(shù)據(jù),基本都是開發(fā)人員在Mac環(huán)境下用Xcode工具,基于被測應(yīng)用源碼或者特定簽名下通過原生的Instruments工具來獲取應(yīng)用冷啟動時間、熱啟動時間、內(nèi)存消耗、幀率等性能指標(biāo)。
對于測試人員來說,首先沒有充足的Mac電腦提供,其次,出于代碼的保密性,無法為測試人員開發(fā)代碼權(quán)限,同時技術(shù)門檻也較高,為了讓測試人員也能進(jìn)行iOS應(yīng)用性能測試,基于代碼外黑盒方式獲取iOS應(yīng)用性能數(shù)據(jù),使用TraceUtility工具解析數(shù)據(jù),在前端頁面用圖表方式為測試人員提供iOS應(yīng)用性能測試服務(wù)。
2.技術(shù)選型和實(shí)現(xiàn)原理
2.1 Instruments工具組件介紹
Instruments是Xcode的一個工具集,為我們提供了強(qiáng)大的程序性能分析及測試能力。它是以一個獨(dú)立的 App 的形式存在的,你可以在 Xcode -> Open Developer Tool -> Instruments 中打開它。打開后功能組件頁面如下圖:
一、Time Profiler使用簡介:
- TimeProfiler見名知意:時間分析工具,它會按照設(shè)定的時間間隔(默認(rèn)1毫秒)來跟蹤每一線程的堆棧信息(stacktrace),并通過比較時間間隔之間的堆棧狀態(tài),來推算出某個方法執(zhí)行了多久,給出一個近似值。
二、CPU Activity Log CPU活動日志工具簡介;
三、Core Animation動畫渲染使用簡介:
四、Activity Monitor內(nèi)存使用情況簡介:
1)Summary(Summary of data) :Process(進(jìn)程)使用內(nèi)存、CPU使用時長等摘要信息:
其中參數(shù)的含義如下:
- process id ——進(jìn)程id
- process name ——進(jìn)程名
- user name——用戶名
- %CPU——cpu占比
- threads——線程
- real mem——真正使用的內(nèi)存
- virtual mem——虛擬內(nèi)存
- architecture——架構(gòu)
- cpu time——CPU時間
- sudden term——突然項(xiàng)(N/A:不適用)
2)Samples(a list of samples) ----一系列抽樣(即不同時間,CPU使用時間、內(nèi)存使用情況的樣本值)
參數(shù)的含義如下:
- Physical Memory Wired——操作系統(tǒng)占用的內(nèi)存
- Physical Memory Active——除操作系統(tǒng)外其他進(jìn)程占用的內(nèi)存
- Physical Memory Inactive——最近被釋放的內(nèi)存
- Physical Memory Used——profiling當(dāng)前進(jìn)程時使用的總內(nèi)存
- Physical Memory Free——當(dāng)前的可用內(nèi)存
- Total VM Size——虛擬內(nèi)存的占用量
五、Energy Usage Level 簡介
查看應(yīng)用的耗電量等級。電量使用level為0-20,1/20:表示運(yùn)行該App,電池生命會有20個小時;20/20:表示運(yùn)行該App,電池電量僅有1小時的生命。
2.2 instruments命令行調(diào)用方法
instruments命令
- usage: instruments [-t template] [-D document] [-l timeLimit] [-i #] [-w device] [[-p pid] | [application [-e variable value] [argument ...]]]
- -t是指定模板;
- -D 指定生成的.trace文件;
- -l 指定運(yùn)行時間,此處單位為ms;
- -w 指定設(shè)備id(把設(shè)備通過usb連接電腦后,設(shè)備id可通過system_profiler SPUSBDataType查看);
application 即待測試的App名;
如下示例:
- 在fcbba9b83bf99c97e5d4d56d99a264d083d5e2cd設(shè)備上啟動”Time Profiler”模板運(yùn)行com.suning.XX錄制30000ms的Profiler.trace文件,輸出路徑為/Users/monky/Work
- instruments -l 30000 -w fcbba9b83bf99c97e5d4d56d99a264d083d5e2cd -v -t “Time Profiler“ -D /Users/monky/Work/time Profiler.trace com.suning.XX
自定義多模板.tracetemplate文件
有時候需要同時監(jiān)控好幾個模板,這個時候可以導(dǎo)出一個自己需要的.tracetemplate文件。
- a.首先打開instruments,在主界面選擇需要測試的模板,如下圖,通過右上角的+添加。
- b.選擇完所有需要的模板后,點(diǎn)擊Instruments -> file -> Save As Template 保存,記錄好保存的位置。
- c.然后就可以用自己的模板進(jìn)行測試
如下實(shí)例:
- Instruments -w fcbba9b83bf99c97e5d4d56d99a264d083d5e2cd -v -t "CustomTemplate" -D templateData.trace com.suning.XX
2.3 instruments數(shù)據(jù)解析功能實(shí)現(xiàn)
我們生成一個自定義的數(shù)據(jù)模板MyTemplate.tracetemplate,根據(jù)instruments工具生成的trace文件,使用TraceUtility對文件進(jìn)行解析,獲取存儲的信息。
Trace 文檔的基本結(jié)構(gòu)
文檔結(jié)構(gòu)的邏輯能從 Instruments 的交互邏輯看出來,一份文檔有一個目標(biāo)設(shè)備,一個監(jiān)測的進(jìn)程和一組 profiling 模版,然后可以使用同一組模版進(jìn)行多次 profile。而對應(yīng)到 Instruments 的代碼中,一份文檔就是一個 XR Trace 對象,除了一些元數(shù)據(jù),它還包含一個 XR Instrument 對象的數(shù)組,其中每一個,又包含了一個 XR Run 的數(shù)組。
所以接下去要做的事情就是,找到從不同模版的 XR Instrument 中讀取 XR Run 對象中的數(shù)據(jù)的方法,然后依次遍歷即可。
XR Instrument對象
數(shù)據(jù)讀取和保存的代碼主要在 InstrumentsAnalysisCore.framework 這個框架里,存儲格式也用了 SQLite,把各種讀取寫入查詢都抽象了出來,比如用戶在 Instruments 里用鼠標(biāo)選了一段時間來看這段時間的數(shù)據(jù),這樣的過濾操作就不需要在每個模版里單獨(dú)實(shí)現(xiàn)了。同時,因?yàn)閿?shù)據(jù)的結(jié)構(gòu)種類也比較有限,比如調(diào)用棧樹,樣本列表。
XRContext
在 Instruments 里,XRContext 就體現(xiàn)在模版列表下面的這個導(dǎo)航條。它是樹結(jié)構(gòu)的,每次選中顯示一個 context,那從根結(jié)點(diǎn)到這個 context 就是一條 context path。XRContextContainer(通常是 view controller)保存著 context 的引用,叫做它的 contextRepresentation,而 XRContext 也引用一個真正展示它數(shù)據(jù)的 XRContextContainer(通常是 view),叫做它的 container。
不同的模版當(dāng)然會有不同的 contexts,但是有時候一個模版也會包含多個不同的 contexts,所以在用戶選擇不同的模版查看數(shù)據(jù),或者從那個導(dǎo)航條里切換當(dāng)前模版的不同的數(shù)據(jù)視圖的時候,當(dāng)前的 context 就會變化,新的 context 的 -[XRContext display] 方法被調(diào)用,然后這個 context 會通過 -[XRContextContainer displayContext:] 傳給相對應(yīng)的 XRContextContainer,然后這個 container(通常是 view controller)就可以加載數(shù)據(jù),刷新視圖了。
也就是說文檔中的大部分?jǐn)?shù)據(jù)只有在真正需要顯示的時候才會被讀取,從 Instruments 用戶的角度來看很容易理解,不過對于 TraceUtility 的用戶來說,就是需要知道,如果自己讀取的數(shù)據(jù)都是 nil,或者空數(shù)組之類的,就可以看看是不是忘記調(diào)用這個 -[XRContext display]方法了。
每一種XRContextContainer對象存儲的結(jié)構(gòu)層次各有不同,以下給出三種結(jié)構(gòu)解析方法。
TimeProfiler模板解析實(shí)例:
CPU Activity Log模板解析實(shí)例:
Connections 模板數(shù)據(jù)解析實(shí)例:
Search Paths
雖然說要調(diào)用 Instruments 的代碼只需要鏈接上它的 framework 就可以了,不過這里還有幾個值得一提的地方。
首先是編譯器搜索我們要鏈接的 framework 的目錄。參考 Xcode 項(xiàng)目配置的 FRAMEWORK_SEARCH_PATHS 變量。
- /Applications/Xcode.app/Contents/SharedFrameworks
- /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/Frameworks
如果這個沒有設(shè)置對的話,鏈接的時候會報(bào)錯,沒法生成可執(zhí)行程序。
然后是編譯好的程序在啟動過程中搜索這些動態(tài)鏈接的 framework 的目錄。參考 Xcode 項(xiàng)目配置的 LD_RUNPATH_SEARCH_PATHS 變量。
- /Applications/Xcode.app/Contents/SharedFrameworks
- /Applications/Xcode.app/Contents/OtherFrameworks
- /Applications/Xcode.app/Contents/Developer/Library/Frameworks
- /Applications/Xcode.app/Contents/Developer/Library/PrivateFrameworks
- /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/Frameworks
如果這個沒有設(shè)置對的話,程序還是可以編譯,但是程序運(yùn)行的時候會報(bào)錯。另外,這里不僅包含上一個配置里的目錄,還多了別的,是因?yàn)槲覀冩溄拥?framework 還依賴了別的 framework,這些 framework 也需要在運(yùn)行的時候由 dyld 一起加載。
最后是 Instruments 自己搜索 Packages 的目錄,這些目錄都在 Instruments.app 的安裝目錄下,而函數(shù) NSString *PFTInstrumentsAppContents() 就是用來獲取這個安裝目錄的。它通過調(diào)用 +[NSBundle mainBundle] 來確定當(dāng)前進(jìn)程是 Instruments 的主 App 還是附加的命令行工具,然后返回正確的結(jié)果。
然而在我們的進(jìn)程中,+[NSBundle mainBundle] 返回的結(jié)果并不能被這個函數(shù)正確識別和處理,所以我們需要 hook 這個方法來返回 Instruments.app 所對應(yīng)的 bundle,從而使得 Instruments 能夠正確找到需要加載的包。
2.3解析后數(shù)據(jù)
Time Profiler解析出數(shù)據(jù)如下圖:
CPU Activity Log解析出數(shù)據(jù)如下圖:
Core Animation解析出數(shù)據(jù)如下圖:
Activity Monitor內(nèi)存使用情況解析出數(shù)據(jù)如下圖:
Energy Usage Level解析出數(shù)據(jù)如下圖:
Connections解析出數(shù)據(jù)如下圖:
3.應(yīng)用效果
蘇寧蛙測平臺將instruments檢測iOS性能技術(shù)應(yīng)用在iOS穩(wěn)定性測試中,將用戶提測的任務(wù)結(jié)果收集分析后制作成圖表展示,方便測試人員直接高效的獲得目標(biāo)測試App在不同系統(tǒng)版本、機(jī)型上的性能表現(xiàn),提高相關(guān)人員的產(chǎn)出效率。如下圖測試報(bào)告節(jié)選截圖:
4.總結(jié)
考慮到文章篇幅,本文僅介紹了蘇寧蛙測平臺在移動端性能檢測的冰山一角,有關(guān)于移動穩(wěn)定性測試其他技術(shù)點(diǎn)將會在后續(xù)文章中進(jìn)行分享。蛙測平臺會在大促期間力保每一個上線應(yīng)用安全、穩(wěn)定、健壯,站好第一班崗,為蘇寧軟件質(zhì)量保駕護(hù)航。同時我們也會不斷成長,提升技術(shù)面,將“測試,原來可以如此簡單!”作為自己前進(jìn)的目標(biāo),為蘇寧智慧零售戰(zhàn)略提供堅(jiān)實(shí)保障。
作者:
錢夢奇,蘇寧易購IT總部數(shù)據(jù)云公司移動SDK工程師,主要從事測試工具與平臺的研發(fā)工作。專注于移動App開發(fā)、測試流程和測試工具開發(fā),對移動端自動化測試、穩(wěn)定性測試、性能測試、App開發(fā)技術(shù)和新理念實(shí)踐,積累了比較豐富的經(jīng)驗(yàn)。
【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請注明原文作者和出處為51CTO.com】