iOS 平台基础性能数据采集与实践

-回复 -浏览
楼主 2019-10-17 14:49:22
举报 只看此人 收藏本贴 楼主

引言


本文是 TalkingData 张永超老师在内部做的 KOL 分享内容总结,分享了他在 iOS 平台上进行基础性能数据采集的实践心得


你也可以点击下方语音收听我们的分享。



大家好,这次分享的内容是关于 iOS 平台的一些基础性能数据的采集和一些应用实践,内容可能比较多,关于代码的部分就不详细讲解了,谢谢。


随着互联网的发展,现在已经进入了移动互联网时代,最初是横向发展,大批量的应用程序上架,这些应用不是很注重应用的用户体验。近几年来,应用程序已经向纵深发展,用户也越来越关心用户体验,对开发者来说,就必须关注应用的性能所带来的用户流失问题。


用户流失问题又是目前应用程序存活的关键问题,这样就牵扯到整个应用的性能,数据是如何来定义、分类和收集的?


1. 什么是性能数据?


首先看一下性能数据的定义。在计算环境中,也就是在整个操作系统中,应用程序的性能是衡量应用程序是否可用的一个指标。通俗一点说,所有可能影响应用程序实际运行情况的数据指标,都可以理解为是性能问题。再稍微延伸一点,就像我们经常听说的 APM,也就是应用性能管理,它是一个比较新的网络管理方向,目前已经延伸到了整个应用程序的性能管理,主要针对的是企业一些关键业务的应用程序的监测、优化,目的是提高应用程序的可靠性和质量,保证用户的保有量,降低 IT 的成本。


APM 是目前所有应用厂商都比较关心的一个问题,也有一些应用厂商将 APM 的一些服务作为单独的一个组件发布,比如说国内网易的 NeteaseAPM,oneAPM,国外的 New Relic,还有听云、Bonree 等等,它们都是将 APM 这一个详细的功能作为一个产品服务来推向市场,让更多的开发者以更低的成本来加入应用程序性能的监控等等。


关于性能数据的定义做一个总结,在应用程序的运行环境中,不管是哪个平台,影响到应用程序可用性的指标,都可以认定为是一个性能数据,这是一个比较通俗的定义,也比较好理解。


以上是第一部分,相对简单一点,对性能数据做了一个简单的介绍。


2. 性能数据的分类


第二部分是关于性能数据的分类,这里据不完全统计,大概有十种影响应用程序性能的问题,分别是网络连接超时、应用闪退、应用卡顿、应用崩溃、网络劫持、交互性差、CPU 使用率、内存泄露、接口不良,甚至是黑白屏。


开发者很难兼顾所有的性能问题,而且在传统的开发流程中,我们解决性能问题主要是靠线上用户的反馈,反馈之后开发者才能够去分析应用性能的瓶颈在哪里,然后修复、再发布。对用户来说,这是一个漫长的等待过程,他势必会把你的应用列为待卸载的状态,也可能直接卸载了。


如何避免这种情况?解决方法是在应用的开发前期或者在线上,我们有一套完整的应用性能数据采集和监控的流程,这样对一个应用来说,能够达到实时监控其性能指标的目的。


对于 iOS 来说,由于 iOS 平台本身是一个相对封闭的系统,所有的东西都是苹果公司说了算,它开放或不开放对开发者的影响比较大。简单地说,iOS 平台下的应用性能指标,有这么几个分类,一个是资源的消耗情况,这里包括 CPU、内存的消耗,流量的消耗、电量的消耗等,另一个是应用的运行情况,包括图像、视图的渲染情况、应用加载时间等。


这几项可以作为 iOS 平台上面基础性能数据的一个收集、分类,有了分类之后,我们就可以逐项采集相关数据来做分析,判断是否影响到应用的可用性。


3. iOS 平台上的基础性能数据采集


但是在开始之前,有三个问题要思考,第一个是为什么要做性能数据的采集?也就是说为什么要做性能的监控和测试,第二个问题,做完这些性能数据的采集之后,有什么用?第三个问题就是怎么做?


下面来逐一解答这三个问题。首先第一个问题,为什么要在正式环境中做性能数据的采集?在很多企业里面,App 在开发过程和上线后,都会有一些功能方面的测试与 API 的测试,并且比较成熟。但即使是这样,不管 App 怎么优化,架构多么好,最终的应用是基于手机平台来运行的,不同的平台可能会给应用造成在开发和测试阶段无法预知的一些问题。 这就是要做性能数据的采集和测试的原因。


第二个问题是做完有什么用?我们先回顾一下传统的 App 发布情况:开发人员在开发阶段进行开发,开发完成之后测试人员逐个场景、逐个步骤反复测试,但是这个过程可能会来来回回好几遍,造成的问题就是人力、物力、包括时间都消耗在了开发-测试-开发的循环之中。


有了性能数据的实时采集,应用程序在测试阶段只要保证功能完善,就可以进行线上发布,发布之后,我们有一套完整的线上性能数据采集的功能在 App 里面,那么对接到的后台服务就实时地拿到了应用程序在运行阶段的一些性能数据,这些性能数据可能对应的场景步骤都不相同,通过对这些性能数据的分析,我们可以对应用程序进行资源优化,然后再进行发布,省去了从用户的反馈,到测试人员和开发人员再不断调优测试的循环。


第三个问题是怎么去做?苹果公司的开发者工具 Xcode,已经提供了一套工具,叫 Instruments,是集成 Xcode 里面的一个组件,用这个工具,可以把这些数据在开发阶段进行测试和调优,但是开发阶段的测试和调优并不等同于线上环境的实际情况,因为用户不同,平台不同,手机的硬件也不同,所以线上环境的监控会更加重要一些。


第三部分内容是这些性能数据到底在 iOS 平台是如何去采集?以及苹果公司是不是对这些性能数据的采集提供了友好的 API 等。


第一个是 CPU,中文叫中央处理器,英文叫 Central Processing Unit,是整个计算机的主要设备之一,主要功能是解释计算机的指令以及处理计算机软件中的数据。


对于 iOS 平台来说,它是最重要的计算资源之一。比较糟糕的应用程序可能会造成整个 CPU 持续高负载运行。对用户来说,一方面最直接的影响就是造成应用卡顿,另一方面是手机发烫,电量会快速消耗,严重影响到用户体验。一个合理的应用程序,它的 CPU 可能会在某一瞬间有高的增长,但是增长完成之后它会趋于平稳。要知道一个 App 的 CPU 占用率,在 iOS 平台需要了解的知识挺多的。


第一个就是线程,线程是调度和分配的基本单元,在作为应用程序的进程运行时,它包含了多个不同的线程,这一点也是和安卓平台不同的,安卓平台是允许多个进程同时存在的,iOS 平台一个应用程序是一个进程,一个进程里面有多个线程,也就是说一个应用程序相当于含有多个线程的进程。


另外 iOS 平台是基于 Apple Darwin 内核,由 kernel、XNU 和 runtime 三部分组成的,而 XNU 是 Darwin 的内核,它的意思就是“X is not UNIX”的缩写,是一个混合内核,但是这个混合内核是由 Mach 微内核和 BSD 组成的。那么 Mach 内核的话是一个轻量级的一个操作系统平台,它只能完成一个操作系统最基本的职责,比如刚才说到的进程、线程、虚拟内存、管理,还有任务的调度,进程之间的通信,消息的传递等等。其他像文件的操作,设备的访问等都是由 BSD 层来实现的。


进程子系统的架构图


而上面这张图是 iOS 平台和 macOS 中进程子系统的一个架构图,它俩之间的相同点就是整个线程技术都是基于 Mach 线程技术实现的,在 Mach 层中有一个结构体, 叫做 thread_basic_info,它这个结构体中提供了线程的基本的信息。


thread_basic_info


上面提到了那个 Mach task 可以看作是一个机器无关的线程执行环境。一个它所包含了它的整个线程列表,在 iOS 内核中提供了一个 task_threads 的 API 调用,用来获取整个 task 的线程列表,然后就可以通过 thread_info 来查询整这个线程的一些信息,它整个结构体是下面这样子的。


task_threads 结构体


有了这个结构体之后,可以得到整个线程列表,这样每一个线程所占用的 CPU 就可以计算出来,最终可以得到 App 的 CPU 占用情况。我们不仅可以拿到这个 App 的 CPU 占用情况,也可以拿到 CPU 的一些其它信息,比如 CPU 的频率,包括最大频率和最小频率,这些数据也是能够体现出来一个 App 的 CPU 使用情况的。


下面看一下另一个比较重要的性能数据指标,就是内存的使用情况,这类内存主要是物理内存,物理内存与 CPU 一样是系统中比较稀少的资源,也是最容易发生资源竞争的一个单元,与应用的整个性能也是直接相关的。在 iOS 平台上通常的官方做法是牺牲别的应用来保证当前应用的内存使用,当应用处于后台时,它会自动监控这个应用所需内存的情况,在达到一定时间之后,它会把这个应用所需的内存全部 Kill 掉,然后把这些内存让给当前应用来使用。


那么内存是如何获取的?苹果也提供了对应的一个结构体,这个结构体是 mach_task_basic_info,在这个 mach_task_basic_info 结构体中会给出几个内存的大小,包括虚拟内存、物理内存等等一些其他的信息,通过结构体可以拿到系统中 App 在运行时的一些内存使用情况,整个结构体如下。


mach_task_basic_info 结构体


接下来介绍应用的启动时间的衡量指标,应用的启动在 iOS 平台来说它分为两种方式,一种是冷启动,一种是热启动,冷启动就是应用完全没有运行过,当用户点击应用的 icon,然后应用才加载到最终呈现的界面,这是冷启动方式。


热启动是当应用在前台时,按了 home 键将应用置于后台,再从后台唤醒应用到前台的过程,这叫热启动。这是两种不同的启动方式,在 iOS 平台上运行的方法也不同,通常情况下是在这两种方法中加入一定的计时,来衡量、记录与采集该应用的启动时间。


应用启动时序图


上面这张图就是苹果官方给出的一个应用启动的时序图,从这个图中可以看到两种方式,一种是 Launch Time 部分,也就是绿色部分,是冷启动方式,下面 Running 部分是热启动过程,右边 Your Code 这部分是应用程序中的一些代码,热启动和冷启动对应的应用中所调用的方法或者说所响应的方法是不同的,所以我们可以在不同的方法中加入计时来衡量最终整个应用程序的启动时间。


计算运行时间


上面这张图是整个 App 运行时间是如何计算的,这里大家主要看一下,main 函数之前和 main 函数之后,这两部分对照上面这个图应该可以大体明白 iOS 平台冷启动、热启动以及总的应用启动时间的计算方式了。


下面是最后一个分享的采集点,就是渲染的效果,渲染效果主要收集的是 FPS,也就是每秒的帧数,FPS 是测量用于保存显示动态视频的信息数量,每秒钟帧数越多显示的动作就会越流畅,一般情况下都是保持在 50 和 60,这样的话用户用起来比较流畅。


在 iOS 平台上没有直接获取 FPS 的 API,但是在 Xcode 提供的工具中能够监测到 FPS,为了能够在线上环境中使用,我们这里采用了另外一种方式,就是监测应用视图刷帧频率,也就是刷新界面的次数。


FPS 过低的情况下出现的直接问题就是卡顿,卡顿对用户来说可能是最不能忍受的一个现象。所以在开发阶段,如果开发者能够实时监控整个视图的 FPS 情况,对应用的优化、FPS 的调优都是很好的一个参考数据。


对 FPS 的收集牵扯到 iOS 平台一些底层的内容,如它的 RunLoop,RunLoop 是 iOS 平台底层的运行循环,这里不再过多细讲,只能说 iOS 平台上能够收集到的 FPS 不是真实的 FPS,只能作为开发者和测试的一个参考指标。


这一部分内容相对比较多,也比较杂,所以暂时先讲到这里。具体的代码,包括里面一些函数的说明,感兴趣的话可以参考 Apple 性能指南,其中涵盖了多种性能相关的说明文档。


4. 性能数据的用途


接下来看一下性能数据的用途,性能数据我们采集上来之后到底有什么用途?有一个关键的点就是 iOS 平台下应用程序发布之后都有哪些痛点?如果找到这些痛点,我们就能知道应用性能数据的意义和用途在哪里。


首先 iOS 平台的应用必须在 App Store 中下载,这是苹果自家掌控的一个平台,用来做应用程序的发布和一些其他业务。发布之后,开发者如果遇到了一些应用程序上面的问题,或者用户看到应用程序的上的问题,必须由开发者根据这些问题去找问题所在的原因、修复,然后再发布到 App Store 中。


App Store 有一个比较头疼的问题就是审核周期,虽然现在苹果已经加快了审核周期,但是这个审核周期可能仍然无法满足 App 遇到一些严重问题的修复和发布进度。


因此如果 iOS 的开发者能够在应用发布之后,实时监控应用程序的一些性能问题、稳定性问题、电量问题、兼容性问题等等,就可以在用户可能还没有发现的前提下把应用程序修复,提交 App Store。这样就省去了用户发现问题、报给开发者、开发者修复之后再提交 App Store,App Store 审核周期又很长,导致了用户可能无法忍受而直接卸载 app。


简单总结一下性能数据的用途,它最大的意义就在于开发者能够快速地发现问题,修复问题。


5. 性能数据采集的未来


最后一个问题是性能数据采集的未来,在整个应用数据采集的过程中,很多人觉得移动应用平台或者说 App 里面能够采集的数据已经没有了,只能是目前的状况。其实不一定,只能说看似比较明显的数据,我们已经采集了,但是一些深层次的数据可能还没有被发现,或者说可能我们认为它还不重要,所以说应用数据的采集在后期的话可能会是一个比较漫长的过程。


6. Q&A


Q1:苹果是否有性能数据的工具?


A1:苹果的开发者工具 Xcode 内置的一个 Instruments 的应用性能数据监测工具。但是这些工具开发者只能在开发和测试的时候用,并不能够在线上的环境中使用,因此这块我们会做一些线上环境数据的采集,来帮助开发者在线上环境中对应用的性能进行分析,优化等等。


Q2:我们的 SDK 集成到客户的 app 中是一个线程的方式被客户 app 调用的吗?我们的 SDK 在客户 app 中运行的整个生命周期中只有一个线程吗?


A2:我们的 SDK 并不是在客户的应用程序中以单一的线程执行,因为苹果允许用户自己去创建某段代码或者某个功能所运行的线程,所以说我们的 SDK 会有多个线程,那么多个线程是在适当的时机去创建,然后使用完成之后去销毁,以避免应用的 CPU、内存这些性能数据的异常等等。


Q3:我们的 SDK 对客户 app 会造成影响吗?


A3:我们的 SDK 对于用户 app 的影响,第一是 app 的大小会增大,增大的幅度大小取决于客户 app 开发者打包时的 Xcode 设置。


第二个影响,就是最终客户 app 的使用者,流量会略有增加,但是我们的 SDK 已经对所需要发送的数据进行了最小化的压缩,甚至对带宽的使用也进行了一些优化,这样使它的流量消耗非常非常低,可以说是忽略不计。目前,我们在正在进一步的优化 SDK,为了最小化各种影响,我们一直在努力。


题图来自:akket.com

我要推荐
转发到