当前位置: 首页 > 科技观察

如何评价一个App的稳定性和质量?

时间:2023-03-20 12:50:53 科技观察

“崩溃”与“卡住”、“异常退出”同为影响App稳定性的三种常见情况。相关数据显示,当iOS的死机率超过0.8%,Android的死机率超过0.4%时,活跃用户数明显下降。不仅会造成关键业务中断、用户留存率下降、品牌美誉度下降等负面影响,还会直接导致卸载和流失。同时,给开发商带来不小的资金损失。那么,崩溃率低的应用程序质量高吗?App的稳定性能直接通过崩溃率来判断吗?首先,衡量一款App的好坏,我们需要定义一个统一的口径,即哪些指标可以作为稳定性评估的口径?以友盟+的U-APM定义的稳定率概念为例,评价一个App的稳定性和质量,一般考虑以下三点:用于评估计算;异常退出,如:低内存杀手、从任务列表划掉、系统异常、断电、用户触发关机/重启等,使用异常率指标来评估计算。crash,即程序出现异常,导致程序退出。包括:Java崩溃,即Java代码中出现未捕获的异常,导致程序异常退出。如:空指针异常、数组越界异常等。Native异常,即在Native代码中,发生错误产生相应的signal信号,导致程序异常退出。如:访问非法地址、地址对齐问题等。Java崩溃的捕获比较简单,而Native崩溃的捕获可能需要我们对系统的底层知识有一定的掌握。我们知道Android是基于Linux系统的,系统的崩溃大多是编码错误或者硬件错误导致的。当系统遇到不可恢复的错误时,会通过异常中断触发异常处理过程,这些中断的处理统一到一个信号量中。当应用程序收到一个信号量时,会根据内核的默认动作进行处理,如Term、lgn、Core、Stop、Cont。同时我们也可以通过sigaction注册接收信号来指定处理动作,比如抓取crash信息等。当然在捕获的过程中会遇到一些困难,尤其是在极端环境下,比如栈溢出的时候,因为栈空间已经用完了,我们的信号处理函数就无法调用,从而无法捕获到crash信息.这时候我们就需要考虑使用signalstack,让我们的信号处理函数可以在堆中分配一块内存空间作为“可替换信号栈”来处理crash信息。当然,除了稳定安全的抓包能力,还需要丰富崩溃现场的上下文信息,比如Logcat信息、调用栈信息、设备信息、环境信息等,以提供全面的参考以便日后定位和解决问题。对于崩溃,我们使用崩溃率作为数据指标。包括:UV崩溃率,即崩溃错误的去重用户数/总去重活跃用户数;PV死机率,即死机错误次数/启动次数;启动崩溃率,即应用程序启动时发生的崩溃,是一个很容易被忽视的非常重要的崩溃指标,因为启动是APP生命周期中非常重要的一个阶段。在这个过程中会暴露出很多广告、闪屏、活动等,同时还要进行各种初始化,而且如果启动出现错误,往往无法弥补热修复和降级灾害防护策略。ANR,即ApplicationNotResponding,当应用在一段时间内没有及时响应时,会弹出ANR对话框,让用户选择继续等待或强制关闭。从用户体验的角度来看,有时候ANR带来的体验可能比crash还差,所以开发者在关注crash的同时也要高度重视ANR。ANR捕捉的准确率一直是一个不断升级、不断提升的过程。早期我们使用FileObserver来监控/data/anr/traces.txt文件的变化来抓取和报告,但不幸的是随着版本升级,系统和厂商开始收紧系统文件的权限,并且该解决方案的覆盖率越来越低,导致ANR捕获的准确性一直下降。然后我们改进为监听消息队列的运行时间来捕捉ANR,即在主线程Looper中放入一条空消息,5秒后监听空消息是否被执行,但是这种方案并不能真正捕捉到ANR情况(有遗漏和误报),无法获取完整的ANR内容。后续我们参考AndroidANR的实现原理,实现了一套实时准确的ANR抓拍方案,兼容所有系统版本。我们知道,系统的system_server进程在检测到APP出现ANR后,会向ANR进程发送SIGQUIT(信号3)信号。默认情况下,系统的libart.so会收到这个信号,调用Java虚拟机的dump方法产生traces。通过拦截SIGQUT,我们在ANR发生时首先接收信号,并生成跟踪和ANR日志。处理完信号后,我们继续将信号传递给系统,让系统生成traces文件。在生成traces文件时,我们保证内容与原系统保持一致,同时生成traces文件的速度得到了显着提升,有效避免了由于可能导致的再次被system_server使用SIGKILL(信号9)杀死生成痕迹的时间太长。同时,我们对捕获的内容进行了丰富,包括:触发ANR的原因,手机中TOP进程的CPU使用率,A??NR进程中TOP线程的CPU使用率,CPU核心处理时间的分布,以及磁盘IO操作的等待时间。解决ANR问题提供更强大的支持!同样对于ANR的发生,我们也分为UVANR率和PVANR率。算法可以参考上面崩溃率的计算。当然,除了崩溃和ANR,我们往往会忽略异常退出等场景,但通过异常退出,我们往往可以发现内存不足杀手、系统重启等无法正常捕获的问题。例如,兼容性问题导致的闪退、设备重启、第三方库主动调用退出函数导致应用闪退次数增多等难以发现的问题。因此,我们可以通过异常退出率来全面了解和衡量应用的稳定性。综上所述,我想大家应该对文章开头的问题有了答案。当然,为了掩盖代码质量问题,我们不应该使用手动trycatch来避免某些问题,可能会打断用户的正常使用,造成感性阻塞反馈。我们应该从用户使用APP时的真实感受出发,出现问题及时发现并处理。应用稳定性是一个长期迭代的过程。在这个过程中,U-APM是一个非常好的提高效率和降低成本的工具。它提供了收集、解析、聚合和分析的能力。下一期我们将从如何通过U-APM解决和处理闪退、ANR等问题进行讲解,敬请期待。