Instrument 10
1 Instrument 10 架构
主要分为两个部分 Standard UI
(界面) 和 Analysis Core
(分析核心)
1.1
其中 Standard UI
也是分为两部分 : table
(蓝色部分)和 graph
(红色部分).
其中
table
又大致分为5种格式1 List (列表)
2 Aggregation (聚合显示)
3 Call Tree (就是timeprofile 中的堆栈)
4 Narrative (叙事)
5 Time Slice (时间片)
graph
的话基本分为4种显示
1 Plot
2 Automatic Treatment
3 Plot Template
image.png
4 Histogram (矩形图)
2 graph
和table
的数据来源.
这就到了介绍 Analysis core
的时候了。首先就是收集,存储[不需要我们实现], 分析(合并), 可视化。
一个数据的展示流程
Tracing -> Schemas/Modeling -> Visualization
2.1 数据源
数据源 通过 定义的os_singPost
或者 molder
规则产生数据, 我们利用收集到的数据 去定义 Schema
,可以说 Instrument 的所有可视化都是依赖于Schema
,因为定义的 modeler
也是要输出到 Schema
中
Schema
分为
<1 <os-signpost-interval-schema>
对应我们自定义的 os_singPost
或者modeler
<2 <point-schema>
点类型 schema
2.2 如何在schema
使用数据源
<1 os_singPost
的数据源 需要在 schame
中 <start-pattern>
<end-pattern>
中的定义 和 代码中定义的 参数名 一致。
代码中的定义
case .downloading:
os_signpost(.begin, log: SignPostLog.imageLoadLog, name: SignPostLog.imgDownload, signpostID:OSSignpostID(log: SignPostLog.imageLoadLog, object: self),"Image name:%@", name)
case .success:
os_signpost(.end, log: SignPostLog.imageLoadLog, name: SignPostLog.imgDownload, signpostID:OSSignpostID(log: SignPostLog.imageLoadLog, object: self),"download result:%@, time:%d", "success", time)
case .cancel:
os_signpost(.end, log: SignPostLog.imageLoadLog, name: SignPostLog.imgDownload, signpostID:OSSignpostID(log: SignPostLog.imageLoadLog, object: self),"download result:%@, time:%d", "cancel", time)
Schema
中的定义
<os-signpost-interval-schema>
<!-- 数据捕捉 -->
<start-pattern>
<message>"Image name:"?image-name</message>
</start-pattern>
<end-pattern>
<message>"download result:" ?result ", time:" ?time</message>
</end-pattern>
</os-signpost-interval-schema>
<2 关于使用 modeler
进行数据源采集
需要到 CLIPS
语法定义 modeler
规则 进行数据收集, 然后在自定义的 Instrument 配置文件中增加 <modeler>
模块
先看一个示例
<!-- 建模器 -->
<modeler>
<id>com.coderhg.dt.download.Anitipatterns</id>
<title>Anti-patterns modeler</title>
<purpose>Generates warnings into detected</purpose>
<production-system>
<rule-path>duplicate-call-detection.clp</rule-path>
</production-system>
<output>
<schema-ref>downloader-narrative</schema-ref>
<required-input>
<schema-ref>os-signpost</schema-ref>
</required-input>
</output>
</modeler>
此modeler
是数据规则 在duplicate-call-detection.clp
文件中定义, 输出的schema
是 downloader-narrative
,还有一个必须要强制导入的 os-signpost
(系统的 Schema) 的依赖。
然后 在 downloader-narrative
的 schema
中将 modeler
采集到的数据 再定义成需要使用的 column
供给 instrument
使用。
Sorry:本文暂不涉及 modeler
文件的编写。
2.3 然后将数据定义成 column
提供给 instrument
中定义的 table
和 graph
如下就是将image-name数据 转换成 column
, 还可以自己定义如何展示column
的规则
<os-signpost-interval-schema>
<!-- 定义数据结构 -->
<column>
<mnemonic>image-name</mnemonic>
<title>image-name-title</title>
<type>string</type>
<expression>?image-name</expression>
</column>
<column>
<mnemonic>impact</mnemonic>
<title>Impact</title>
<type>event-concept</type>
<!-- 如果size?大于2 就是 高 否则 是 低 -->
<expression>(if (> ?size 2) then "High" else "Low")</expression>
</column>
</os-signpost-interval-schema>
3 Instrument
3.1 Instrument的结构
Instrument 的格式采用 xml 。
主要分为三部分
1 基本参数定义 Instrument
的 一些基本参数(名称、描述、id、icon) ,更多的还可以从外部引入其他 parameter
参数
<instrument>
<id>com.mm.uitest.DownloaderInstrument.downloader</id>
<title>Instruement-title</title>
<category>Behavior</category>
<purpose>Download-purpose</purpose>
<icon>Generic</icon>
<import-parameter>
<from-scope>trace</from-scope>
<name>?target-pid</name>
</import-parameter>
</instrument>
2 创建 table
,table
一定要引入 schema
<instrument>
<create-table>
<id>image-download-table</id>
<schema-ref>image-download-schema</schema-ref>
</create-table>
</instrument>
3 创建可视化(graph
or table
)就是第一部分说的 标准UI 部分, 数据依赖于 第二部定义的 table
, 所有数据源都必须是 table
中依赖的 schema
中定义的 column
, 具体展示格式可以根据需要进行调整。
以list
为例
<instrument>
<list>
<title>image-download-list</title>
<table-ref>image-download-table</table-ref>
<column>image-name</column>
<column>image-result</column>
<column>image-time-mnemonic</column>
</list>
</instrument>
苹果详细的 Instrument 配置 格式文档
一下是一个完整的Instrument 结构
<package>
<!-- package定义 -->
<!-- 定义或者 引入系统的schema -->
<import-schema>os-signpost</import-schema>
<os-signpost-interval-schema>
......
<column></column>
</os-signpost-interval-schema>
<!-- 定义modeler -->
<modeler>
......
</modeler>
<!-- 定义Instrument -->
<instrument>
<!-- 基本参数定义 -->
<id>com.mm.DownloaderInstrument.downloader</id>
<title>Image Download</title>
<category>Behavior</category>
<purpose>ShowImageDownPurpose</purpose>
<icon>Generic</icon>
<!-- 创建table 必须要依赖某个 schema -->
<create-table>
<id>image-download-table</id>
<schema-ref>image-download-schema</schema-ref>
</create-table>
<!-- 可视化 -->
<graph>
<title>Background Images</title>
<lane>
</lane>
</graph>
<list>
<title>image-download-list</title>
<table-ref>image-download-table</table-ref>
<column>image-name</column>
</list>
</instrument>
总结: 所有的可视化数据 都是来自于table 而table 又依赖于 自定义或者 苹果已经实现的schema
。所以所有的数据都需要换成 schema
中的 column
4 自定义展示一个 time-profile
此处我因为没有读懂 time-profile
中modeler
源码,所以数据源无法自定义,只能获取 time-profile
的数据并自定义的展示出来。
time-profile
的 modeler
的源码推测是在 此路径中
Xcode.app ▸ Contents ▸ Applications ▸ Instruments.app ▸ Contents ▸ Packages ▸ Sampling.instrdst ▸ Contents ▸ Extensions ▸ com.apple.dt.instruments.time-profiler.dtac
1、首先在自定义的 Instrument 中 引入 time-profile
所在的 package (sampling)
, SystemTrace
是 另一个package.
系统的
schema
和 package
可以通过 Instrument
的 preferences
查看 我们自定义的 package
也会在这里展示出来image.png
2、通过查看time-profile
的配置xml
文件 ,可知time-profile
中所有暴露出的所有 column
,所有的column
都可以为我们所用
xml
文件所在路径 Xcode.app ▸ Contents ▸ Applications ▸ Instruments.app ▸ Contents ▸ Packages ▸ Sampling.instrdst ▸ Contents ▸ Extensions ▸ com.apple.dt.instruments.sampling.dtac
3、如此自定义展示需要的column
3.1 package中引入 time-profile
3.2 在Instrument 中 创建表格
3.3 可视化 time-profile
中的 column
备注: 在苹果的文档中透漏了一部分 time-profile
的 xml部分源码,但是time-profile
的具体 modeler
的源码 可能是在 Sampling.instrdst
的 Extension
中.
3.4 代码。
<package>
<id>com.mm.uitest.DownloaderInstrument</id>
<title>DownloaderInstrument</title>
<owner>
<name>mumu</name>
</owner>
<import-schema>time-profile</import-schema>
<instrument>
<id>com.mm.uitest.DownloaderInstrument.downloader</id>
<title>Instruement-title</title>
<category>Behavior</category>
<purpose>Download-purpose</purpose>
<icon>Generic</icon>
<import-parameter>
<from-scope>trace</from-scope>
<name>?target-pid</name>
</import-parameter>
<create-parameter>
<name>?recordWaitingThreads</name>
<boolean-value>
<true-choice>Record Waiting Threads</true-choice>
</boolean-value>
</create-parameter>
<create-parameter>
<name>?highFreqSampling</name>
<boolean-value>
<true-choice>High Frequency</true-choice>
</boolean-value>
</create-parameter>
<create-parameter>
<name>?recordKernelStacks</name>
<boolean-value>
<true-choice>Record Kernel Call Stacks</true-choice>
</boolean-value>
</create-parameter>
<create-table>
<id>image-stack-table</id>
<schema-ref>time-profile</schema-ref>
<attribute>
<name>needs-kernel-callstack</name>
<parameter-ref>?recordKernelStacks</parameter-ref>
</attribute>
<attribute>
<name>high-frequency-sampling</name>
<parameter-ref>?highFreqSampling</parameter-ref>
</attribute>
<attribute>
<name>record-waiting-threads</name>
<parameter-ref>?recordWaitingThreads</parameter-ref>
</attribute>
<attribute>
<name>target-pid</name>
<parameter-ref>?target-pid</parameter-ref>
</attribute>
</create-table>
<list>
<title>image-stack-list</title>
<table-ref>image-stack-table</table-ref>
<column>time</column>
<column>stack</column>
<column>thread</column>
<column>process</column>
<column>weight</column>
<column>thread-state</column>
</list>
<calltree>
<title>DemoCallTree</title>
<table-ref>image-stack-table</table-ref>
<backtrace-column>stack</backtrace-column>
<thread-column>thread</thread-column>
<category-column>thread-state</category-column>
<weight-column>weight</weight-column>
</calltree>
</instrument>
可视化效果
image.png
image.png
后续深入:
1 time-profile如何获取数据源,modeler 绑定方法 ,定义规则
2 (time-profile是从kernel 获取堆栈信息) 比timer-profile更灵活的使用 kernel 中的 堆栈.
3 更细致的理解 package
的参数使用
难点: CLIPS 语法理解
和实际在 modeler
中的使用
参考
WWDC 2018:创建自定义的 Instrument
Xcode 中自定义 Instruments
WWDC 405_measuring_performance_using_logging
WWDC 410_creating_custom_instruments
WWDC 414_developing_a_great_profiling_experience
WWDC 418_using_time_profiler_in_instruments
WWDC 421_modeling_in_custom_instruments