【问题标题】:Alternative to DTSendSignalFlag to identify key events in Instruments?替代 DTSendSignalFlag 来识别 Instruments 中的关键事件?
【发布时间】:2023-03-23 04:39:01
【问题描述】:

曾经有一个不错的工具DTSendSignalFlag,它是DTPerformanceSession 框架的一部分,您可以通过它以编程方式将标志插入到仪器中(请参阅Xcode Instruments trace comparison)。此功能在 iOS 7 中停止工作。

有没有人成功让DTSendSignalFlag 在 iOS 7 中工作?信号标志是(曾经?)通过代码以编程方式在 Instruments 中发布标志的有用方法(在诊断 Instruments 中的复杂应用程序时非常有用),但是当我在 iOS 7 模拟器上运行时,我没有在 Instruments 中看到我以编程方式创建的标志(但是当我为 iOS 6 模拟器构建 Xcode 5 时它可以工作)。

【问题讨论】:

  • 我找不到任何提及这一点,如果它消失了,也找不到替代品。希望能够得到这样的工作。

标签: ios xcode-instruments dtsignalflag


【解决方案1】:

我们现在可以使用在 Instrument 的“兴趣点”中捕获的以编程方式插入的路标,而不是使用标志。

在 iOS 13 和 macOS 10.15 中,我们可以使用os_signpost。这在 WWDC 2019 视频Getting Started with Instruments 中有说明。

例如,在 Swift 中:

  • 导入统一的日志框架:

    import os.log
    
  • 为兴趣点创建OSLog

    private let pointsOfInterest = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: .pointsOfInterest)
    
  • 当你想开始一个兴趣点范围时,你可以.begin一个兴趣点:

    let id = OSSignpostID(log: pointsOfInterest)
    os_signpost(.begin, log: pointsOfInterest, name: "Download", signpostID: id, "Download %d", index)
    
  • 当你想结束一个兴趣点范围时,你可以.end它:

    os_signpost(.end, log: pointsOfInterest, name: "Download", signpostID: id, "Download %d", index)
    
  • 如果您对某个时间范围不感兴趣,而对单个路标感兴趣,则可以发布.event

    os_signpost(.event, log: pointsOfInterest, name: "Done", "All done")
    

或者在 Objective-C 中:

  • 导入统一的日志记录路标框架:

    @import os.signpost;
    
  • 为兴趣点创建OSLog

    os_log_t log = os_log_create("ViewController", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
    
  • 当你想开始一个兴趣点范围时,你可以.begin一个兴趣点:

    os_signpost_id_t identifier = os_signpost_id_generate(log);
    os_signpost_interval_begin(log, identifier, "Download", "Started %d", index);
    
  • 当你想结束一个兴趣点范围时,你可以.end它:

    os_signpost_interval_end(log, identifier, "Download", "Finished %d", index);
    
  • 如果您对某个时间范围不感兴趣,而对单个路标感兴趣,则可以发布.event

    os_signpost_event_emit(log, OS_SIGNPOST_ID_EXCLUSIVE, "Done");
    

无论如何,“兴趣点”工具现在可以在 Instruments 中以图形方式表示一系列下载和解析操作(每个队列限制为每个队列两个并发操作):

请注意,name 值(一组我使用了名称Download,另一组我使用了Parse)在兴趣点工具中很好地分成了不同的泳道。而且因为我使用了可选的格式字符串,我实际上可以看到消息,我可以清楚地将每个下载和解析操作与我的应用程序中的特定任务相关联。

上面我使用了可选的OSSignpostID 参数,因为我有多个重叠的范围,我想避免将特定的.end 与相应的.begin 相关联的任何混淆。如果您不使用兴趣点范围或没有重叠范围,则在不可能存在歧义的情况下,从技术上讲,您不需要使用此可选参数。 (即使您使用这些路标标识符,请确保关联的.begin.end 路标的name 也匹配,否则仪器不会将它们识别为同一兴趣点范围的开始和结束,即使使用相同的路标 ID。)

无论如何,既然您已经拥有填充了信息的“兴趣点”工具,您可以双击一个范围来选择它,或者三次单击它来设置您的检查范围。


在 iOS 10 和 macOS 10.12 中,我们使用了kdebug_signpost。这在 WWDC 2016 视频System Trace in Depth 中有说明。

对于那些花费离散时间的进程,我们可以使用kdebug_signpost_startkdebug_signpost_end。例如:

kdebug_signpost_start(SignPostCode.download.rawValue, UInt(index), 0, 0, SignPostColor.orange.rawValue)
performDownload {
    kdebug_signpost_end(SignPostCode.download.rawValue, UInt(index), 0, 0, SignPostColor.orange.rawValue)
}

要标记一个时刻,我们可以使用kdebug_signpost

kdebug_signpost(SignPostCode.done.rawValue, 0, 0, 0, SignPostColor.red.rawValue)

第一个参数只是一些唯一的数字代码,对应于我们将在 Instruments 中使用的“路标代码名称”。你可以使用任何你想要的值(介于 0 和 16383 之间),但我使用一些指定任务类型的值:

enum SignPostCode: UInt32 {   // some custom constants that I'll reference in Instruments
    case download = 0
    case parse = 1
    case done = 2
}

其余参数可以是您想要的任何 UInt 值,但在我的示例中,我将使用第二个参数作为唯一标识符来匹配重复的 startend 调用,我将使用最后一个参数在 Instruments 中对我的区域进行颜色编码:

enum SignPostColor: UInt {    // standard color scheme for signposts in Instruments
    case blue = 0
    case green = 1
    case purple = 2
    case orange = 3
    case red = 4
}

完成此操作后,您可以在 Instruments 中配置应用程序,单击 Instruments 工具栏右侧的“+”按钮,然后添加“Points of Interest”。通过配置“路标代码名称”以匹配我作为第一个参数传递给路标的数值,仪器实际上会为我翻译这些代码。一旦我对应用进行了概要分析,我现在就可以清楚地突出显示我的兴趣点:

在此快照中,我分析了七个下载操作(橙色)和七个解析操作(绿色),一次限制为两个。当他们完成后,我张贴了一个“完成”路标(红色针脚)。但是这个演示应用程序的细节并不重要,而这只是说明了如何在 Instruments 的“兴趣点”中呈现单个路标和开始/结束路标。

主要问题是我现在在我的代码中的事件和我在 Instruments 中看到的事件之间有了明确的对应关系。如果需要,我可以控制-单击路标范围列表中的条目并告诉仪器“设置时间过滤器”,这样当我回到我的其他仪器(分配或时间探查器或其他),检查范围被过滤到我的应用程序中的相关兴趣点。


注意,以上是 Swift。在 Objective-C 中,kdebug_signpost API 是类似的,但你必须包括:

#import <sys/kdebug_signpost.h>

显然,您为代码定义枚举的方式也会发生变化。

注意,这个kdebug_signpost API 是在 iOS 10/macOS 10.12 中引入的。标头告诉我们早期的操作系统版本可以使用syscall

在以前版本的操作系统中,应用程序可以使用:

syscall(SYS_kdebug_trace, APPSDBG_CODE(DBG_MACH_CHUD, <your event code>) | DBG_FUNC_<type>, arg1, arg2, arg3, arg4);

记录仪器将显示的事件。 syscall(2) 现已弃用,此接口取代了上述调用。

注意:如果您发现自己必须在较早的操作系统版本上使用 syscall,则必须导入 &lt;sys/kdebug.h&gt;

#import <sys/kdebug.h>

另外,我在任何标题中都找不到SYS_kdebug_trace 的声明,但偶然发现了网上的参考资料,上面说这个值为180,我凭经验验证了这一点:

#ifndef SYS_kdebug_trace
#define SYS_kdebug_trace 180
#endif

【讨论】:

  • 有没有办法在 Instruments 中保存/应用常用的路标配置(例如,帮助调试共享公共代码库的多个应用程序)?有什么方法可以直接使用 dtrace(而不是使用 Instruments)来监控路标事件?很好的答案,顺便说一句!
  • @lilinjn - 在 Instruments 的“文件”菜单中使用“另存为模板...”选项。然后,下次您运行 Instruments 时,不要选择其中一个标准工具,而是单击“自定义”,您将在那里看到您保存的模板。重新dtrace,我不知道。
  • 我可以控制新 API 中的颜色吗?我真的很想念……我知道它会为我分组,但我不能动态分配组名——那是什么落后的 API……
  • @PauliusLiekis - AFAIK,新 API 不会公开用于颜色编码的第四个参数。从理论上讲,您可以只使用 kdebug API 并失去通道,但获得着色,并忽略/抑制弃用警告。但这只是一个短期的解决方案。
  • @PauliusLiekis 您还可以编写自己的自定义工具并使用Event Concept Engineering Type 来控制颜色(通过引用显式颜色名称或语义“事件概念”值。参见stackoverflow.com/a/67852179/1271826(其中例如,我正在诊断定制仪器的一个特殊特性)。定制仪器有点复杂,但一旦你克服了如何做到这一点的重要障碍,给车道上色就变得非常简单。
【解决方案2】:

2019

路标已使用更简单的 API 进行了更新。视频在这里(Time: 20:40

https://developer.apple.com/videos/play/wwdc2019/411/

请参阅 Apple 日志记录文档中的调试 CPU 性能

https://developer.apple.com/documentation/os/logging

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多