MetricKit。 iOS应用程序性能分析

图片

新玩具


我们将继续熟悉WWDC上发布的Apple的新材料。 这次,考虑MetricKit ,这是一个全新的框架,可以用作监视应用程序性能的工具。

众所周知,在开发过程中衡量应用程序性能很容易。 Xcode显示使用的RAM数量和处理器负载,您可以使用Instruments将其连接到被测模拟器或设备,甚至编写自己的工具(有关更多详细信息,请参见有关定制工具包的文章: 第1 部分 / 第2部分 )。 仅了解性能调整的重要性并不能使您评估应用程序几乎所做的所有事情。 但是,如果开发的应用程序是针对实际用户的,那么当我们谈论AppStore时,事情就会变得更加复杂。 无论您多么仔细地测试应用程序,在实际条件下,总会有很多令人惊奇的事情会影响性能和用户体验。 当然,有很多工具可用于收集各种参数,但是大多数工具都受iOS SDK以及实际监视对应用程序行为的影响所限制。

今年,苹果决定填补这一空白,并为开发人员提供了一种工具,可帮助他们在现实环境中收集和分析应用程序性能指标。 他们宣布在Xcode 11组织者中的单独选项卡上提供MetricKit (一种框架,该框架可访问操作系统提供的选项),您可以在其中找到应用程序设置。 我们将在MetricKit中暂停,因为Xcode中的参数显示仅适用于AppStore中已经发布的应用程序。

图片

MXMetricManager


该框架的体系结构非常简单明了。 中心部分由MXMetricManager类占据,该类是一个单元素结构,可为开发人员提供大量框架API。

通常,工作流包含3个主要步骤:

  1. 您初始化MXMetricMnager并为其指定观察者。
  2. 如果需要,您可以使用Signpost API在应用程序中实现自己的指标
  3. 最后,现在我们在didReceivePayloads方法中处理接收到的数据,即 将它们发送到您的后端进行进一步分析。

参数以MXMetricPayload实例数组的形式出现 。 有效负载封装了元数据集和时间戳。 度量有效负载是MXMetric子类的简单包装。 对于每种类型的参数,它都是单独的。

Apple很好地记录了指标的类型,因此我们不要在此花太多时间。 但是,您应该停止注意到一件有趣的事情-MXMetric提供了一个开放的API以NSDictionary或JSON对其进行序列化,我认为这有点不寻常。

MetricKit的内部组件。


在外面,MetricKit看起来很简单。 但是,从内到外查看一切工作原理总是很有趣。 如果您要面对一项特定的任务,那么沉浸在更深层次的事物中总是很吸引人的。 因此,我决定要传递带有MetricKit标记的参数,然后让它们随时为我提供更新的度量。 当然,您可以在Xcode中使用` Debug-> Simulate MetricKit Payloads` ,但是id不允许您显示自己的数据。 是的,这不是一个非常有用的团队,但是它为您的研究提供了方向,看起来非常有趣;)

要开始任务,我们显然需要MetricKit本身。 您可能会认为,为框架获取二进制文件很容易,因为一旦通过“将二进制文件链接到库”对话框添加Xcode,它就会在框架列表中显示它。 这是一个非常乐观的想法。 因为如果打开MetricKit.framework ,您将看到MetricKit.tbd文件。 它的大小只有4kb 。 显然,这不是我们想要的。

那么,这里到底发生了什么?

TBD代表“基于文本的dylib存根”,实际上是一个YAML文件,带有dylib描述,用于导出字符和dylib二进制文件的路径。 链接到tbd文件会减少二进制文件的大小。 稍后,在运行时,将在tbd文件中指定的路径下从操作系统下载真正的dylib二进制文件。 这是在Xcode中打开文件时的样子:

图片

使用tbd文件中的路径,您可以轻松获取MetricKit二进制文件以进行进一步的研究,但是还有一种更简单的方法。

我们的应用程序二进制文件在Mach-O标头部分中包含每个动态链接库的路径。 使用-l标志可以使用该工具轻松检索此信息。

这是我创建的测试项目的输出:

→ otool -l ./Metrics | grep -i metrickit name /System/Library/Frameworks/MetricKit.framework/MetricKit (offset 24) 

您可以看到与前面在tbd文件中看到的相同的路径。 有了二进制框架文件,您可以看一下内部元素。 为此,我通常使用料斗拆卸器 。 这是一个易于使用但非常强大的工具,用于仔细研究二进制文件。

MetricKit二进制文件打开后,立即转到“处理”选项卡 并展开“标签”列表。 在这里您可以看到所有导出的字符。 选择其中一个(例如MXMetricManager),我们将看到其所有方法,选择了一个方法后,我们将在右侧看到其内容:

图片

当查看MXMetricManager方法列表[ https://gist.github.com/deszip/88a258ae21d33dc75d7cbac9569c6ec1 ]时,很容易注意到_checkAndDeliverMetricReports方法。 这似乎是为了使MetricKit向订户提供更新而需要调用的内容。

不幸的是,尝试呼叫他并没有导致呼叫用户,这可能意味着这些参数将不会被传递。 考虑到该方法的实现,我们注意到一些有趣的事情:它枚举/ Library / Caches / MetricKit / Reports目录的内容。

然后,他尝试为磁盘上的每个项目解压缩MXMetricPayload实例。 最后,它对注册的订户进行迭代,并使用数据列表调用didReceive方法。

问题可能是/ Library / Caches / MetricKit / Reports中没有数据,但是我们知道我们需要一些MXMetricPayload的存档实例。 因此,让我们创建它们并将它们放在磁盘上,然后调用“ _checkAndDeliverMetricReports ”。 同样,计划是创建MXMetricPayload的实例,然后创建并添加任何类型的MXMetric,然后将数据实例存档到磁盘。 毕竟,调用' _checkAndDeliverMetricReports '方法,这将导致使用存根作为参数调用我们的订户。

查看有关有效负载和指标的Apple文档,您可能会注意到它们没有公共初始化程序,并且大多数属性都是只读的。 那么,如何实例化一个类呢?

再次回到Hopper以查看MXMetricPayload方法的列表:

图片

在这里,您可以看到其初始化程序和分配参数的方法。 由于Objective-C的动态特性,使用NSInvocation类和“ performSelector”方法可以很容易地调用私有方法。

例如,我们将为CPU创建指标并将其添加到有效负载中。 使用此链接,您可以找到完整的代码片段:[ https://gist.github.com/deszip/a0cf877b07cc2877129e0aaef2fed1e4 ]。

最后,我们将创建的所有内容存档,并将数据写入/ Library / Caches / MetricKit / Reports目录

现在是时候调用“ _checkAndDeliverMetricReports ”方法了,该方法最终将导致对订户的调用。 这次我们传递带有有效负载存根的数据作为参数。

指标来自哪里


通过MetricKit可以很容易地获取报告,但是您可能有兴趣了解报告在app / Library目录中的显示方式。 这是怎么回事。

在MetricKit二进制文件中,我注意到此方法:“ _ createXPCConnection”。 检查其实现可以弄清情况-它为服务建立了一个NSXPCConnection,名称为com.apple.metrickit.xpc ,并为客户端和服务器端提供了两个接口MXXPCServerMXXPCClient 。 如果您查看协议说明:

图片

结论


MetricKit是一个独特且不可或缺的工具,用于在生产中的实际条件下维护应用程序的性能。

不幸的是,除了在WWDC会话的演示过程中显示的内容之外,目前无法查看Xcode中的“ Metric”用户界面。

图片

通过消除代码中的性能问题,它可以成为将用户体验提升到新水平的宝贵工具。

我现在在此工具中看到的一个缺点是每种类型都缺少详细信息:只有分离是应用程序的版本,并且您看不到特定的一组设备/操作系统版本/区域等指标。

但是,当然,总会有机会将数据与所需的重要信息一起发送给您自己,以进行进一步处理。 您可以将其附加到错误跟踪器等中的任务上。 在AppSpector,我们的团队正在努力使用从MetricKit获得的数据来扩展性能监视工具的功能。

保持最新!

Source: https://habr.com/ru/post/zh-CN468347/


All Articles