建議先作以下兩件事,若是不想看也沒有關係:
一、看 Creating Custom Instruments,由於當前文章就是看了這個教程草總結的。
二、我實現的代碼在這裏 CustomInstruments, 歡迎下載。
三、下載以後,先看一下 os_log 初體驗
中的簡單例子,瞭解一下 oslog
與 os_signpost
的簡單使用。
四、須要簡單的瞭解一下 CLIPS 語法。
當前文章主要是根據 wwdc2018 & 410 中所說起到的內容進行實現,拿不到視頻中的代碼,那就只能本身模擬。git
這個很簡單,直接經過這個界面的指示建立一個 Mac 項目便可。
github
HGCustomInstruments
項目中直接建立了,在實際開發中,若是這個工具是針對某個項目的話,這個會更方便些。建立以後是這樣的:
instruments
源文件問題,能夠參考這個討論:
Splitting up instruments code。
注意: 這是一個 Mac 應用,應該這樣去運行:
數據庫
HGTick
用。在這裏能夠看到具體的信息:
HGTick
是不可用的,畢竟尚未開始寫代碼。
打開文件(HGTick.instrpkg),是這樣的:express
XML
格式的,經過不一樣的標籤標示不一樣的功能,若是圖中的
package
的標籤,標示一個包,緊接着是其子標籤:
id
、
title
與
owner
等等。接下來就要開始寫代碼了:
<!-- 導入 tick 模塊 至關於 `import` -->
<import-schema>tick</import-schema>
複製代碼
具體的含義在註釋中已經有所體現,說明 tick
模塊是系統已經存在的,咱們直接經過 import-schema
標籤進行導入便可。編程
<!-- 開始構建一個 instrument -->
<instrument>
<id>com.coderhg.ticksinstrument</id>
<title>Ticks-IT</title>
<category>Behavior</category>
<purpose>tick demo</purpose>
<icon>Generic</icon>
<!-- 建立一個表, 這個表中使用到了 `tick` -->
<create-table>
<id>tick-table</id>
<schema-ref>tick</schema-ref>
</create-table>
<!-- 軌道視圖 -->
<graph>
<title>Ticks-GH</title>
<lane>
<title>Ticks-LE</title>
<table-ref>tick-table</table-ref>
<!-- 軌道視圖顯示的數據 -->
<plot>
<value-from>time</value-from>
</plot>
</lane>
</graph>
<!-- 詳情視圖 -->
<list>
<title>Ticks-LT1</title>
<table-ref>tick-table</table-ref>
<column>time</column>
</list>
<list>
<title>Ticks-LT2</title>
<table-ref>tick-table</table-ref>
<column>time</column>
</list>
</instrument>
複製代碼
這就是核心實現 Instruments
功能的代碼了,詳細解釋以下:
一、使用了 Instrument
以後依舊須要添加對應的標識、標題等基本信息。
二、須要建立一個對這個自定義的 Instrument
須要有一張對應的表(table),故須要使用 create-table
,值得注意的是這個表所須要的數據是直接來自於 tick
schema。
三、開始建立一個軌道視圖,這個軌道視圖的數據來自 tick-table
這張表,因爲這張表引用系統的 tick
schema,tick
中有一個 time 屬性,因此能夠直接使用這個時間戳字段。
四、詳情視圖,使用 list
標籤主要是在詳情視圖中顯示數據的。這個 list
至關於咱們開發中的 UITableView
,tick-table
至關於數據源(dataSource)。
選擇 HGTick
json
schema
,叫
tick
。
tick
中提供的
time
屬性爲自定義的表格提供數據。
注意: 這個例子沒有實際的意義,僅僅是爲了後面的介紹,作一個簡單的鋪墊。api
這個主要是模擬解析 JSON 字符串的,爲了簡單起見,我就弄一個模擬 JSON 的方法。這個須要對開發的項目代碼有侵入性的。因此將模擬的代碼以下:bash
/// Touch
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// log 句柄
let parsingLog = OSLog(subsystem: "com.coderhg.json", category: "JSONDecode")
// 開始
os_signpost(.begin, log: parsingLog, name: "Parsing", "Parsing started")
// 模擬: Decode the JSON we just downloaded
let size = jsonDecode()
// 結束
os_signpost(.end, log: parsingLog, name: "Parsing", "Parsing finished SIZE:%ld", size)
}
/// 模擬事件
func jsonDecode() -> UInt32 {
// 0 ~ 3.0 秒的時間
let timeOut = (arc4random()%6)/2
sleep(timeOut)
// 模擬當前解析字符串的大小
let size = arc4random()%100 + 10
return size
}
複製代碼
注意: 這是在咱們開發的代碼,咱們主要是爲了檢測 jsonDecode 方法的,在這裏生成一個隨機數來標識解析所需的時間。
其實,經過以上的代碼已經發現出現了其它的代碼,主要是 os_signpost
api。是的,這個就是爲告終合自定義 Instruments 的時候使用的,只能在這裏寫了開始與結束,在自定義中才能有所匹配,才能作更精細的分析。app
接下來就是看看在對應的 HGJSONDecode.instrpkg
文件中的實現。
os-signpost-interval-schema 標籤使用,目的是自定義一個 schema
,具體的以下所示:dom
<!-- 能夠理解成一個數據來源 -->
<os-signpost-interval-schema>
<id>json-parse</id>
<title>JSON Decode</title>
<!-- 這三個是與項目中一一對應 -->
<subsystem>"com.coderhg.json"</subsystem>
<category>"JSONDecode"</category>
<name>"Parsing"</name>
<!-- 開始匹配-->
<start-pattern>
<message>"Parsing started"</message>
</start-pattern>
<!-- 結束匹配-->
<end-pattern>
<message>"Parsing finished SIZE:" ?data-size-value</message>
</end-pattern>
<!-- 表中的一列 -->
<column>
<!-- 助記符標識, 在 graph 與 list 中只認這個標識 -->
<mnemonic>data-size</mnemonic>
<title>JSON Data Size</title>
<!-- 數據的類型 size-in-bytes -->
<type>size-in-bytes</type>
<!-- 顯示 data-size 的值 -->
<expression>?data-size-value</expression>
</column>
<!-- https://help.apple.com/instruments/developer/mac/current/#/dev66257045 -->
<column>
<mnemonic>impact</mnemonic>
<title>Impact</title>
<type>event-concept</type>
<expression>(if (> ?data-size-value 80) then "High" else "Low")</expression>
</column>
</os-signpost-interval-schema>
複製代碼
上面的代碼,憑藉本身的開發經驗,應該是能看懂的,即便是我每一偶告訴你這是另外一門編程語言:CLIPS。自信觀察 start-pattern
與 end-pattern
這兩個標籤,就應該明白其含義:主要是獲取項目中JSON 解析的開始與結束的。其中在結束的時候會匹配出項目中的元數據:解析字符的大小。這裏主要使用的就是 CLIPS 語言的變量。接着就是 column
, 這個標籤即便爲這個 shema
定義一些字段,在這裏也發現,這裏提到的 schema
很像一個數據庫。其中這個是數據庫中有兩個 key:data-size
與 impact
,其中 impact
是由 data-size-value
的值決定的,大於 80
時值是 High
, 不然爲 Low
。
剩餘的部分,就與 HGTick
中的相似了。最終的效果是這樣的:
這樣就是很清楚的看到每次 JSON 解析的開始與結束,以及執行所花的時間。在實際開發中可能還會同時選中其它的調試模塊,好比 Time Profiler
、內存檢測
等,這樣能很好的全方位的分析當前的運行環境以及運行狀態。
主要就是模擬圖片下載的例子,項目中的核心代碼,以下:
/// 下載狀態
var loadStatus:HGImageLoadStatus? {
didSet {
// 未知
if loadStatus == .HGImageLoadStatusUnkown {
return
}
// ID
let signpostID = OSSignpostID(log: HGSignpostLog.imageLoadLog, object: self.obj!)
let address = unsafeBitCast(self.mockData!, to: UInt.self)
// 開始
if loadStatus == .HGImageLoadStatusIng {
os_signpost(.begin, log: HGSignpostLog.imageLoadLog, name: "Background Image", signpostID: signpostID, "Image name:%{public}@, Caller:%lu", name!, address)
return
}
var status = "finish"
// 完成
if loadStatus == .HGImageLoadStatusFinish {
}
// 取消
if loadStatus == .HGImageLoadStatusCancel {
status = "cancel"
}
os_signpost(.end, log: HGSignpostLog.imageLoadLog, name: "Background Image", signpostID: signpostID, "Status:%{public}@, Size:%lu", status, needTime!)
}
複製代碼
換句話來講,就是模擬圖片下載,而後在上面的代碼中進行 os_signpost
調用。主要是看 HGImageDownload 中的實現。關於這部分,內容相對比較多,可是相比於前面兩個主要多了建模器的構建相關的內容。 這部分,不打算在這裏 copy 代碼,根據上面的介紹經過項目代碼應該很容易能理解。主要關注的標籤是:point-schema
、modeler
、aggregation
與 narrative
,以及 CLIPS 文件 uplicate-call-detection.clp
。
最終的運行效果是:
主要是圍繞 WWDC2018/410 進行介紹。
一、HGTick 簡單的使用了一下系統的 schema tick
模塊,基本認識了自定義 Instruments 的套路以及基本格式。
二、HGJSONDecode 自定義了一個 schema 從項目中經過 os_signpost 獲取感興趣的信息,獲取元數據最終進行分析以及顯示。
三、經過 HGImageDownload 實現了自定義 Instruments 的高級應用,主要是建模器的構建。
綜上: 經過當前介紹,基本上能知道自定義 Instruments 的流程已經相關應用。
使用 Instruments 檢測內存泄漏
WWDC 2018:建立自定義的 Instrument
Xcode 中 Instruments(Time Profiler) 的注意事項