Android NDK开发详解之调试和性能分析的应用启动分析和优化

在应用启动期间,您的应用会给用户留下第一印象。应用在启动时必须快速加载并显示用户使用应用所需的信息。如果您的应用启动时间过长,用户可能会因为等待时间过长而退出应用。

我们建议使用 Macrobenchmark 库测量启动时间。该库提供概览信息和详细的系统跟踪信息,以便您确切了解启动期间发生的情况。

系统跟踪记录提供有关设备上所发生情况的实用信息,可帮助您了解应用在启动期间执行的操作,并确定存在优化空间的方面。

如需分析应用启动,请执行以下操作:

设置在应用启动期间记录跟踪数据的环境。
了解系统跟踪。
使用 Android Studio 性能分析器或 Perfetto 浏览跟踪报告。

分析和优化启动的步骤

应用在启动期间通常需要加载对最终用户至关重要的特定资源。非必需资源可等到启动完成后再加载。

为做出适当的性能权衡,请考虑以下因素:

使用 Macrobenchmark 库测量每项操作所用的时间,并确定需要很长时间才能完成的区块。

确认资源密集型操作是否对应用启动至关重要。如果操作可以等到应用完整绘制后再执行,则有助于最大限度地减小启动期间的资源约束。

确认您是否希望相应操作在应用启动期间执行。很多时候,系统可能会从旧版代码或第三方库调用不必要的操作。

尽可能将长时间运行的操作移至后台。在启动期间,后台进程仍可能会影响 CPU 使用率。

在对操作进行全面研究后,您可以在所需的加载时间与将其纳入应用启动的必要性之间做出权衡。在更改应用的工作流时,请务必留意可能会发生回归问题或破坏性更改。

您可以反复优化和测量,直到您对应用的启动时间感到满意为止。如需了解详情,请参阅使用指标检测和诊断问题。

测量和分析主要操作所用的时间

在获得完整的应用启动跟踪记录后,您可以查看跟踪记录并衡量 bindApplication 或 activityStart 等主要操作所用的时间。我们建议使用 Perfetto 或 Android Studio 性能分析器分析这些跟踪记录。

通过查看应用启动期间所用的总时间,可以找出具有以下特点的操作:

占用大量时间,可以进行优化。每一毫秒都关乎性能。例如,您可以查看 Choreographer 绘制时间、布局膨胀时间、库加载时间、Binder 事务或资源加载时间。一般而言,您可查看所有耗时超过 20 毫秒的操作。
阻塞主线程。如需了解详情,请参阅浏览 Systrace 报告。
不需要在启动期间运行。
可以等到第一帧绘制完毕后再执行。

进一步研究各个跟踪记录,找出性能方面有待改进的方面。

TTID 和 TTFD

如需了解应用生成第一帧所用的时间,请测量初步显示所用时间 (TTID)。不过,此指标不一定反映您的应用启动直至用户可开始与应用互动之间的时间。完全显示所用时间 (TTFD) 指标在测量和优化拥有完全可用应用状态所需的代码路径方面更为有用。

如需了解在应用界面完全绘制后的报告策略,请参阅提高启动时间精确度。

请针对 TTID 和 TTFD 进行优化,因为两者在各自的领域都很重要。较短的 TTID 有助于用户看到应用是真的在启动。保持较短的 TTFD 非常重要,可确保用户能快速开始与应用互动。

分析整体线程状态

选择应用启动时间并查看整体线程切片。主线程需要始终能及时响应。

通过 Android Studio 性能分析器和 Perfetto 等工具可详细了解主线程以及每个阶段所用的时间。如需详细了解如何直观呈现 Perfetto 跟踪记录,请参阅 Perfetto 界面文档。

找出主线程处于休眠状态的主要区块

如果长时间处于休眠状态,可能是因为应用的主线程要等待作业完成。对于多线程的应用,请确定主线程在等待的线程,并考虑优化相关操作。这还有助于确保关键路径不会因为不必要的锁定争用而出现延迟。

减少主线程发生阻塞及进入不可中断的休眠状态的情况

找出主线程每次进入阻塞状态的实例。Perfetto 和 Studio 性能分析器会在线程状态时间轴上用橙色指示器指明这种情况。找出这类操作,查明这些操作是符合预期的,还是可以避免的,并根据需要进行优化。

与 IO 相关的可中断休眠可能是值得改进的方面。 其他执行 IO 的进程(即使是无关的应用)都能与顶端应用在执行的 IO 争用资源。

缩短启动时间

在找到可优化之处后,探索采用一些可能的解决方案来缩短启动时间:

通过延迟和异步方式加载内容,缩短 TTID。
尽量减少进行 binder 调用的调用函数。如果这类函数必不可少,请确保优化其调用,可采用缓存值的方式,而不要重复调用,还可以将非阻塞性作业移至后台线程中。
为了让应用看起来启动更快,可以尽快对用户显示需要呈现的最少内容,让他们不必空等界面的其余部分载入。
创建启动配置文件并将其添加到您的应用。
使用 Jetpack 应用启动库简化应用启动期间的组件初始化。

分析界面性能

应用启动过程包括启动画面和首页的加载时间。为了优化应用启动,请检查跟踪记录,了解绘制界面所用的时间。

限制初始化作业

某些帧的加载时间可能比其他帧更长。我们认为这类帧在应用启动期间的绘制开销很高。

如需优化初始化,请执行以下操作:

优先考虑缓慢的布局传递,选择改进这些方面。
通过添加自定义跟踪事件来分析来自 Perfetto 的提醒和来自 Systrace 的提醒,以减少开销较高的绘制和延迟。

测量帧数据

您可以通过多种方式测量帧数据。以下是五种主要的帧数据收集方法:

使用 dumpsys gfxinfo 进行本地收集:并非 dumpsys 数据中观察到的所有帧都会导致应用呈现速度缓慢,或者对最终用户造成任何影响。不过,观察这项指标在不同发布周期之间的变化,有助于了解总体的性能趋势。如需详细了解如何使用 gfxinfo 和 framestats 将界面性能测量值集成到您的测试实践中,请参阅 Android 应用测试基础知识。
使用 JankStats 进行字段收集:使用 JankStats 库从应用的特定部分收集帧呈现时间,并记录和分析数据。
在测试中使用 Macrobenchmark(在后台使用 Perfetto)
**Perfetto FrameTimeline ** 在 Android 12(API 级别 31)上,您可以从 Perfetto 跟踪记录中收集帧时间轴指标数据,以了解导致帧丢失的作业。如果您想诊断丢帧的原因,不妨从这步入手。
使用 Android Studio 性能分析器检测卡顿

查看主 activity 的加载时间

应用的主 activity 可能包含从多个来源加载的大量信息。请检查首页 Activity 布局,特别是查看首页 activity 的 Choreographer.onDraw 方法。

使用 reportFullyDrawn 向系统报告您的应用现已完全绘制,达到优化目的。
搭配使用 StartupTimingMetric 和 Macrobenchmark 库来测量 activity 和应用启动情况。
查看丢帧情况。
找出在渲染或测量方面很耗时的布局。
找出加载用时较长的资源。
找出在启动期间原本没必要膨胀的布局。

考虑使用以下可优化主 activity 加载时间的解决方案:

尽量简化初始布局。如需了解详情,请参阅优化布局层次结构。
添加自定义跟踪点,以获取有关丢帧和复杂布局的更多信息。
尽量缩减启动期间加载的位图资源的数量和大小。

在布局不会立即 VISIBLE 的地方使用 ViewStub。ViewStub 是一个不可见、零大小的视图,可用于在运行时延迟膨胀布局资源。如需了解详情,请参阅 ViewStub。

如果您使用的是 Jetpack Compose,则可以使用状态获取与 ViewStub 类似的行为,以延迟加载某些组件:
var shouldLoad by remember {mutableStateOf(false)}

if (shouldLoad) {
 MyComposable()
}

修改 shouldLoad,在条件块内加载可组合函数:

LaunchedEffect(Unit) {
 shouldLoad = true
}

这会触发重组,并包含第一个代码段中的条件代码块内的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android NDK开发是指利用NDK(Native Development Kit)将C/C++开发的代码编译成so库,然后通过JNI(Java Native Interface)让Java程序调用。在Android开发中,默认使用的是Android SDK进行Java语言的开发,而对于一些需要使用C/C++的高性能计算、底层操作或跨平台需求的场景,可以使用NDK进行开发。 在Android Studio中进行NDK开发相对于Eclipse来说更加方便,特别是在Android Studio 3.0及以上版本中,配置更加简化,并引入了CMake等工具,使得开发更加便捷。首先要进行NDK开发,需要配置环境,包括导入NDK、LLDB和CMake等工具。可以通过打开Android Studio的SDK Manager,选择SDK Tools,在其中选中相应的工具进行导入。 在项目的build.gradle文件中,可以配置一些NDK相关的参数,例如编译版本、ABI过滤器等。其中,可以通过externalNativeBuild配置CMake的相关设置,包括CMakeLists.txt文件的路径和版本号。此外,在sourceSets.main中还可以设置jniLibs.srcDirs,指定so库的位置。 在进行NDK开发时,可以在jni文件夹中编写C/C++代码,并通过JNI调用相关的函数。通过JNI接口,可以实现Java与C/C++之间的相互调用,从而实现跨语言的开发。 综上所述,Android NDK开发是指利用NDK将C/C++开发的代码编译成so库,并通过JNI实现与Java的相互调用。在Android Studio中进行NDK开发相对方便,可以通过配置环境和相应的参数来进行开发。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值