WWDC-2018笔记---使用Signposts分析App性能

WWDC

Posted by Karim on May 3, 2021

正文

Signposts 可以针对某段代码块进行性能分析,并且能在Instrument中显示,并且允许我们标记一段开始和结束,然后将这两点时间发生的事情与日志关联起来。 代码如下:

import os.signpost

let refreshLog = OSLog(subsystem: "com.example.your-app", category: "RefreshOperations")
//标记单独获取所有图片的开始
os_signpost(.begin, log: refreshLog, name: "Refresh Panel")
for element in panel.elements {
    //标记单独获取一次图片的开始
    os_signpost(.begin, log: refreshLog, name: "Fetch Asset")
    //获取图片
    fetchAsset(for: element)
    os_signpost(.end, log: refreshLog, name: "Fetch Asset")
}
os_signpost(.end, log: refreshLog, name: "Refresh Panel")

同一个方法有可能被多次调用,在 Instrument 上会出现重叠的情况,如果我们希望区分是否是不同的对象调用,可以通过 Signpost IDs 实现。

let spid = OSSignpostID(log: refreshLog)
os_signpost(.begin, log: refreshLog, name: "Fetch Asset", signpostID: spid)

os_signpost(.end, log: refreshLog, name: "Fetch Asset", signpostID: spid)

如果调用的对象本身具有唯一性,还可以用对象作为Signpost IDs

let spid = OSSignpostID(log: refreshLog, object: element)
os_signpost(.begin, log: refreshLog, name: "Fetch Asset", signpostID: spid)

os_signpost(.end, log: refreshLog, name: "Fetch Asset", signpostID: spid)

os_signpost()还允许我们在使用的时候通过格式化字符串的方式增加元数据。

os_signpost(.begin, log: log, name: "Compute Physics",
"for %{public}s at (%d, %.1f) with mass %.2f and velocity (%.1f, %.1f)", description, x1, y1, m, x2, y2)

更有利于我们后续分析和发现追踪特定场景下的问题,这里还要提到一点,对于字符串格式化,这里使用的了%{public}sdescription如果是静态常量的字符串时,可以使用%s,但是需要格式化动态拼接的字符串 时,需要使用%{public}s,为了保护用户的隐私,苹果建议日志都使用静态字符串和数字组成。
还有个小Tips,想让数据在Instrument上以内存大小的单位格式化,可以使用%{xcode:size-in-bytes}llu

苹果在WWDC上声称signpost进行了启动上优化,并且通过编译器的优化,使得它是在编译时运行而不是运行时,并且将很多工作都交给了Instrument,使得signpost在发送的时候只会占用非常少的系统资源。但是你依然有可能想停止signpost的使用。如果想在代码中停止某个signpost的使用,可以通过改变OSLog的初始化实现:

let refreshLog: OSLog
if ProcessInfo.processInfo.environment.keys.contains("SIGNPOSTS_FOR_REFRESH") {
    refreshLog = OSLog(subsystem: "com.example.your-app", category: "RefreshOperations")
} else {
    refreshLog = .disabled //标记为不使用
}
os_signpost(.begin, log: refreshLog, name: "Refresh Panel")
for element in panel.elements {
    os_signpost(.begin, log: refreshLog, name: "Fetch Asset")
    fetchAsset(for: element)
    os_signpost(.end, log: refreshLog, name: "Fetch Asset")
}
os_signpost(.end, log: refreshLog, name: "Refresh Panel")

signpost不仅支持Swift,同时也支持C、OC,API可以参考下图。

signpost如何使用这里就不展开说了,非常简单,在Instrument添加os_signpost的选项卡就可以使用。

参考

Measuring Performance Using Logging

Why the Xcode 8 (iOS 10) print LogMessageLogging in console

Unified Logging and Activity Tracing


请保持转载后文章内容的完整,以及文章出处。本人保留所有版权相关权利。

分享到: