蘇寧蛙測基于Instruments檢測iOS性能技術(shù)
原創(chuàng)【51CTO.com原創(chuàng)稿件】1.背景
在蘇寧智慧零售的戰(zhàn)略中,移動應(yīng)用占據(jù)重要位置,線上應(yīng)用的用戶體驗對于產(chǎn)品推廣有直接影響,而作為移動兩大重要陣營之一的iOS系統(tǒng),應(yīng)用上架前的性能指標(biāo)顯得尤為重要。在不嵌入代碼的前提下,蛙測平臺需要獲得應(yīng)用運行時的內(nèi)存、CPU、FPS、冷啟動時間、熱啟動時間等數(shù)據(jù),提供給開發(fā)部門,進行上線前優(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ù)門檻也較高,為了讓測試人員也能進行iOS應(yīng)用性能測試,基于代碼外黑盒方式獲取iOS應(yīng)用性能數(shù)據(jù),使用TraceUtility工具解析數(shù)據(jù),在前端頁面用圖表方式為測試人員提供iOS應(yīng)用性能測試服務(wù)。
2.技術(shù)選型和實現(xiàn)原理
2.1 Instruments工具組件介紹
Instruments是Xcode的一個工具集,為我們提供了強大的程序性能分析及測試能力。它是以一個獨立的 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(進程)使用內(nèi)存、CPU使用時長等摘要信息:
其中參數(shù)的含義如下:
- process id ——進程id
- process name ——進程名
- user name——用戶名
- %CPU——cpu占比
- threads——線程
- real mem——真正使用的內(nèi)存
- virtual mem——虛擬內(nèi)存
- architecture——架構(gòu)
- cpu time——CPU時間
- sudden term——突然項(N/A:不適用)
2)Samples(a list of samples) ----一系列抽樣(即不同時間,CPU使用時間、內(nèi)存使用情況的樣本值)
參數(shù)的含義如下:
- Physical Memory Wired——操作系統(tǒng)占用的內(nèi)存
- Physical Memory Active——除操作系統(tǒng)外其他進程占用的內(nèi)存
- Physical Memory Inactive——最近被釋放的內(nèi)存
- Physical Memory Used——profiling當(dāng)前進程時使用的總內(nèi)存
- Physical Memory Free——當(dāng)前的可用內(nèi)存
- Total VM Size——虛擬內(nèi)存的占用量
五、Energy Usage Level 簡介
查看應(yīng)用的耗電量等級。電量使用level為0-20,1/20:表示運行該App,電池生命會有20個小時;20/20:表示運行該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 指定運行時間,此處單位為ms;
- -w 指定設(shè)備id(把設(shè)備通過usb連接電腦后,設(shè)備id可通過system_profiler SPUSBDataType查看);
application 即待測試的App名;
如下示例:
- 在fcbba9b83bf99c97e5d4d56d99a264d083d5e2cd設(shè)備上啟動”Time Profiler”模板運行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.選擇完所有需要的模板后,點擊Instruments -> file -> Save As Template 保存,記錄好保存的位置。
- c.然后就可以用自己的模板進行測試
如下實例:
- Instruments -w fcbba9b83bf99c97e5d4d56d99a264d083d5e2cd -v -t "CustomTemplate" -D templateData.trace com.suning.XX
2.3 instruments數(shù)據(jù)解析功能實現(xiàn)
我們生成一個自定義的數(shù)據(jù)模板MyTemplate.tracetemplate,根據(jù)instruments工具生成的trace文件,使用TraceUtility對文件進行解析,獲取存儲的信息。
Trace 文檔的基本結(jié)構(gòu)
文檔結(jié)構(gòu)的邏輯能從 Instruments 的交互邏輯看出來,一份文檔有一個目標(biāo)設(shè)備,一個監(jiān)測的進程和一組 profiling 模版,然后可以使用同一組模版進行多次 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ù),這樣的過濾操作就不需要在每個模版里單獨實現(xiàn)了。同時,因為數(shù)據(jù)的結(jié)構(gòu)種類也比較有限,比如調(diào)用棧樹,樣本列表。
XRContext
在 Instruments 里,XRContext 就體現(xiàn)在模版列表下面的這個導(dǎo)航條。它是樹結(jié)構(gòu)的,每次選中顯示一個 context,那從根結(jié)點到這個 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模板解析實例:
CPU Activity Log模板解析實例:
Connections 模板數(shù)據(jù)解析實例:
Search Paths
雖然說要調(diào)用 Instruments 的代碼只需要鏈接上它的 framework 就可以了,不過這里還有幾個值得一提的地方。
首先是編譯器搜索我們要鏈接的 framework 的目錄。參考 Xcode 項目配置的 FRAMEWORK_SEARCH_PATHS 變量。
- /Applications/Xcode.app/Contents/SharedFrameworks
- /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/Frameworks
如果這個沒有設(shè)置對的話,鏈接的時候會報錯,沒法生成可執(zhí)行程序。
然后是編譯好的程序在啟動過程中搜索這些動態(tài)鏈接的 framework 的目錄。參考 Xcode 項目配置的 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è)置對的話,程序還是可以編譯,但是程序運行的時候會報錯。另外,這里不僅包含上一個配置里的目錄,還多了別的,是因為我們鏈接的 framework 還依賴了別的 framework,這些 framework 也需要在運行的時候由 dyld 一起加載。
最后是 Instruments 自己搜索 Packages 的目錄,這些目錄都在 Instruments.app 的安裝目錄下,而函數(shù) NSString *PFTInstrumentsAppContents() 就是用來獲取這個安裝目錄的。它通過調(diào)用 +[NSBundle mainBundle] 來確定當(dāng)前進程是 Instruments 的主 App 還是附加的命令行工具,然后返回正確的結(jié)果。
然而在我們的進程中,+[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)版本、機型上的性能表現(xiàn),提高相關(guān)人員的產(chǎn)出效率。如下圖測試報告節(jié)選截圖:
4.總結(jié)
考慮到文章篇幅,本文僅介紹了蘇寧蛙測平臺在移動端性能檢測的冰山一角,有關(guān)于移動穩(wěn)定性測試其他技術(shù)點將會在后續(xù)文章中進行分享。蛙測平臺會在大促期間力保每一個上線應(yīng)用安全、穩(wěn)定、健壯,站好第一班崗,為蘇寧軟件質(zhì)量保駕護航。同時我們也會不斷成長,提升技術(shù)面,將“測試,原來可以如此簡單!”作為自己前進的目標(biāo),為蘇寧智慧零售戰(zhàn)略提供堅實保障。
作者:
錢夢奇,蘇寧易購IT總部數(shù)據(jù)云公司移動SDK工程師,主要從事測試工具與平臺的研發(fā)工作。專注于移動App開發(fā)、測試流程和測試工具開發(fā),對移動端自動化測試、穩(wěn)定性測試、性能測試、App開發(fā)技術(shù)和新理念實踐,積累了比較豐富的經(jīng)驗。
【51CTO原創(chuàng)稿件,合作站點轉(zhuǎn)載請注明原文作者和出處為51CTO.com】