Android Studio 3

  • Instrumented: 一个默认配置,在运行时设置应用以在每个函数调用的开始和结束时记录时间戳。 它收集时间戳并进行比较,以生成函数跟踪数据,包括时间信息和 CPU 使用率。 请注意,与设置每个函数关联的开销会影响运行时性能,并可能会影响分析数据,对于生命周期相对较短的函数,这一点更为明显。 此外,如果应用短时间内执行大量函数,则分析器可能会迅速超出它的文件大小限制,且不能再记录更多跟踪数据。
  • Edit configurations: 允许您更改上述“Sampled”和“Instrumented”记录配置的某些默认值,并将它们另存为自定义配置。 如需了解更多信息,请转到创建记录配置部分。
  1. 记录按钮: 用于开始和停止记录函数跟踪。 如需了解更多信息,请转到记录和检查函数跟踪部分。

注: 分析器还会报告 Android Studio 和 Android 平台添加到您的应用进程(如 JDWP、Profile Saver、Studio:VMStats、Studio:Perfa 以及 Studio:Heartbeat,尽管它们在线程活动时间线中显示的确切名称可能有所不同)的线程 CPU 使用率。 这表示 CPU 时间线中应用的 CPU 使用率还可反映这些线程使用的 CPU 时间。 您可以在线程活动时间线中查看其中的一些线程并监控其活动。 (不过,由于分析器线程执行原生代码,因此,您无法为它们记录函数跟踪数据。)Android Studio 将报告此数据,以便当线程活动及 CPU 使用率实际上是由应用代码引发时,您可以轻松识别。

记录和检查函数跟踪

要开始记录函数跟踪,从下拉菜单中选择 SampledInstrumented 记录配置,或选择您创建的自定义记录配置,然后点击 Record 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传。 与应用交互并在完成后点击 Stop recording 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传。 分析器将自动选择记录的时间范围,并在函数跟踪窗格中显示其跟踪信息。如果您想检查另一个线程的函数跟踪,只需从线程活动时间线中选中它。 记录函数跟踪后的 CPU Profiler 视图,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如图所示,记录函数跟踪后的 CPU Profiler 视图包括以下内容:

  1. 选择时间范围: 用于确定您要在跟踪窗格中检查所记录时间范围的哪一部分。 当您首次记录函数跟踪时,CPU Profiler 将在 CPU 时间线中自动选择您的记录的完整长度。 如果您想仅检查所记录时间范围一小部分的函数跟踪数据,您可以点击并拖动突出显示的区域边缘以修改其长度。
  2. 时间戳: 用于表示所记录函数跟踪的开始和结束时间(相对于分析器从设备开始收集 CPU 使用率信息的时间)。 在选择时间范围时,您可以点击时间戳以自动选择完整记录,如果您有多个要进行切换的记录,则此做法尤其有用。
  3. 跟踪窗格: 用于显示您所选的时间范围和线程的函数跟踪数据。 仅在您至少记录一个函数跟踪后此窗格才会显示。 在此窗格中,您可以选择想如何查看每个堆叠追踪(使用跟踪标签),以及如何测量执行时间(使用时间引用下拉菜单)。
  4. 选择后,可通过 Top Down 树、Bottom Up 树、调用图表火焰图的形式显示您的函数跟踪。 您可以在下文中了解每个跟踪窗格标签的更多信息。
  5. 从下拉菜单中选择以下选项之一,以确定如何测量每个函数调用的时间信息:
  • Wall clock time: 壁钟时间信息表示实际经过的时间。
  • Thread time: 线程时间信息表示实际经过的时间减去线程没有消耗 CPU 资源的任意时间部分。对于任何给定函数,其线程时间始终少于或等于其壁钟时间。 使用线程时间可以让您更好地了解线程的实际 CPU 使用率中有多少是给定函数消耗的。

使用 Memory Profiler 查看 Java 堆和内存分配

Memory Profiler 是 Android Profiler 中的一个组件,可帮助您识别导致应用卡顿、冻结甚至崩溃的内存泄漏和流失。 它显示一个应用内存使用量的实时图表,让您可以捕获堆转储、强制执行垃圾回收以及跟踪内存分配。点击 Android Profiler 窗口中的 MEMORY 时间线中的任意位置即可打开 Memory Profiler。或者,您可以在命令行中使用 dumpsys 检查您的应用内存,同时查看 logcat 中的 GC Event

为什么应分析您的应用内存

Android 提供一个托管内存环境—当它确定您的应用不再使用某些对象时,垃圾回收器会将未使用的内存释放回堆中。 虽然 Android 查找未使用内存的方式在不断改进,但对于所有 Android 版本,系统都必须在某个时间点短暂地暂停您的代码。 大多数情况下,这些暂停难以察觉。 不过,如果您的应用分配内存的速度比系统回收内存的速度快,则当收集器释放足够的内存以满足您的分配需要时,您的应用可能会延迟。 此延迟可能会导致您的应用跳帧,并使系统明显变慢。

尽管您的应用不会表现出变慢,但如果存在内存泄漏,则即使应用在后台运行也会保留该内存。 此行为会强制执行不必要的垃圾回收 Event,因而拖慢系统的内存性能。 最后,系统被迫终止您的应用进程以回收内存。 然后,当用户返回您的应用时,它必须完全重启。

为帮助防止这些问题,您应使用 Memory Profiler 执行以下操作:

  • 在时间线中查找可能会导致性能问题的不理想的内存分配模式。
  • 转储 Java 堆以查看在任何给定时间哪些对象耗尽了使用内存。长时间进行多个堆转储可帮助识别内存泄漏。
  • 记录正常用户交互和极端用户交互期间的内存分配以准确识别您的代码在何处短时间分配了过多对象,或分配了泄漏的对象。

如需了解可减少应用内存使用的编程做法,请阅读管理您的应用内存

Memory Profiler 概览

当您首次打开 Memory Profiler 时,您将看到一条表示应用内存使用量的详细时间线,并可访问用于强制执行垃圾回收、捕捉堆转储和记录内存分配的各种工具。Memory Profiler 的默认视图如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如图所示,Memory Profiler 的默认视图包括以下各项:

  1. 用于强制执行垃圾回收 Event 的按钮。
  2. 用于捕获堆转储的按钮
  3. 用于记录内存分配情况的按钮。 此按钮仅在连接至运行 Android 7.1 或更低版本的设备时才会显示。
  4. 用于放大/缩小时间线的按钮。
  5. 用于跳转至实时内存数据的按钮。
  6. Event 时间线,其显示活动状态、用户输入 Event 和屏幕旋转 Event。
  7. 内存使用量时间线,其包含以下内容:
  • 一个显示每个内存类别使用多少内存的堆叠图表,如左侧的 y 轴以及顶部的彩色键所示。
  • 虚线表示分配的对象数,如右侧的 y 轴所示。
  • 用于表示每个垃圾回收 Event 的图标。

不过,如果您使用的是运行 Android 7.1 或更低版本的设备,则默认情况下,并不是所有分析数据均可见。 如果您看到一条消息,其显示“Advanced profiling is unavailable for the selected process”,则需要启用高级分析以查看下列内容:

  • Event 时间线
  • 分配的对象数
  • 垃圾回收 Event

在 Android 8.0 及更高版本上,始终为可调试应用启用高级分析。

如何计算内存

您在 Memory Profiler 顶部看到的数字取决于您的应用根据 Android 系统机制所提交的所有私有内存页面数。 此计数不包含与系统或其他应用共享的页面。 Memory Profiler 顶部的内存计数图例,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

内存计数中的类别如下所示:

  • Java: 从 Java 或 Kotlin 代码分配的对象内存。
  • Native: 从 C 或 C++ 代码分配的对象内存。

即使您的应用中不使用 C++,您也可能会看到此处使用的一些原生内存,因为 Android 框架使用原生内存代表您处理各种任务,如处理图像资源和其他图形时,即使您编写的代码采用 Java 或 Kotlin 语言。

  • Graphics: 图形缓冲区队列向屏幕显示像素(包括 GL 表面、GL 纹理等等)所使用的内存。(请注意,这是与 CPU 共享的内存,不是 GPU 专用内存。)
  • Stack: 您的应用中的原生堆栈和 Java 堆栈使用的内存。 这通常与您的应用运行多少线程有关。
  • Code: 您的应用用于处理代码和资源(如 dex 字节码、已优化或已编译的 dex 码、.so 库和字体)的内存。
  • Other: 您的应用使用的系统不确定如何分类的内存。
  • Allocated: 您的应用分配的 Java/Kotlin 对象数。 它没有计入 C 或 C++ 中分配的对象。

当连接至运行 Android 7.1 及更低版本的设备时,此分配仅在 Memory Profiler 连接至您运行的应用时才开始计数。 因此,您开始分析之前分配的任何对象都不会被计入。 不过,Android 8.0 附带一个设备内置分析工具,该工具可记录所有分配,因此,在 Android 8.0 及更高版本上,此数字始终表示您的应用中待处理的 Java 对象总数。

与以前的 Android Monitor 工具中的内存计数相比,新的 Memory Profiler 以不同的方式记录您的内存,因此,您的内存使用量现在看上去可能会更高些。 Memory Profiler 监控的类别更多,这会增加总的内存使用量,但如果您仅关心 Java 堆内存,则“Java”项的数字应与以前工具中的数值相似。

然而,Java 数字可能与您在 Android Monitor 中看到的数字并非完全相同,这是因为应用的 Java 堆是从 Zygote 启动的,而新数字则计入了为它分配的所有物理内存页面。 因此,它可以准确反映您的应用实际使用了多少物理内存。

注:目前,Memory Profiler 还会显示应用中的一些误报的原生内存使用量,而这些内存实际上是分析工具使用的。 对于大约 100000 个对象,最多会使报告的内存使用量增加 10MB。 在这些工具的未来版本中,这些数字将从您的数据中过滤掉。

查看内存分配

内存分配显示内存中每个对象是如何分配的。 具体而言,Memory Profiler 可为您显示有关对象分配的以下信息:

  • 分配哪些类型的对象以及它们使用多少空间。
  • 每个分配的堆叠追踪,包括在哪个线程中。
  • 对象在何时被取消分配(仅当使用运行 Android 8.0 或更高版本的设备时)。

如果您的设备运行 Android 8.0 或更高版本,您可以随时按照下述方法查看您的对象分配: 只需点击并按住时间线,并拖动选择您想要查看分配的区域。 不需要开始记录会话,因为 Android 8.0 及更高版本附带设备内置分析工具,可持续跟踪您的应用分配。如下如所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果您的设备运行 Android 7.1 或更低版本,则在 Memory Profiler 工具栏中点击 Record memory allocations 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传。 记录时,Android Monitor 将跟踪您的应用中进行的所有分配。 操作完成后,点击 Stop recording 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(同一个按钮)以查看分配。如下如所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在选择一个时间线区域后(或当您使用运行 Android 7.1 或更低版本的设备完成记录会话时),已分配对象的列表将显示在时间线下方,按类名称进行分组,并按其堆计数排序。

注:在 Android 7.1 及更低版本上,您最多可以记录 65535 个分配。 如果您的记录会话超出此限值,则记录中仅保存最新的 65535 个分配。 (在 Android 8.0 及更高版本中,则没有实际的限制。)

要检查分配记录,请按以下步骤操作:

  1. 浏览列表以查找堆计数异常大且可能存在泄漏的对象。 为帮助查找已知类,点击 Class Name 列标题以按字母顺序排序。 然后点击一个类名称。 此时在右侧将出现 Instance View 窗格,显示该类的每个实例,如下图中所示。
  2. Instance View 窗格中,点击一个实例。 此时下方将出现 Call Stack 标签,显示该实例被分配到何处以及哪个线程中。
  3. Call Stack 标签中,点击任意行以在编辑器中跳转到该代码。 有关每个已分配对象的详情在右侧的 Instance View 中的显示,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

默认情况下,左侧的分配列表按类名称排列。在列表顶部,您可以使用右侧的下拉列表在以下排列方式之间进行切换:

  • Arrange by class: 基于类名称对所有分配进行分组。
  • Arrange by package: 基于软件包名称对所有分配进行分组。
  • Arrange by callstack: 将所有分配分组到其对应的调用堆栈。

捕获堆转储

堆转储显示在您捕获堆转储时您的应用中哪些对象正在使用内存。 特别是在长时间的用户会话后,堆转储会显示您认为不应再位于内存中却仍在内存中的对象,从而帮助识别内存泄漏。 在捕获堆转储后,您可以查看以下信息:

  • 您的应用已分配哪些类型的对象,以及每个类型分配多少。
  • 每个对象正在使用多少内存。
  • 在代码中的何处仍在引用每个对象。
  • 对象所分配到的调用堆栈(目前,如果您在记录分配时捕获堆转储,则只有在 Android 7.1 及更低版本中,堆转储才能使用调用堆栈)。

要捕获堆转储,在 Memory Profiler 工具栏中点击 Dump Java heap 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传。 在转储堆期间,Java 内存量可能会暂时增加。 这很正常,因为堆转储与您的应用发生在同一进程中,并需要一些内存来收集数据。

堆转储显示在内存时间线下,显示堆中的所有类类型,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注:如果您需要更精确地了解转储的创建时间,可以通过调用 dumpHprofData()) 在应用代码的关键点创建堆转储。

要检查您的堆,请按以下步骤操作:

  1. 浏览列表以查找堆计数异常大且可能存在泄漏的对象。 为帮助查找已知类,点击 Class Name 列标题以按字母顺序排序。 然后点击一个类名称。此时在右侧将出现 Instance View 窗格,显示该类的每个实例,如下图中所示。
  2. Instance View 窗格中,点击一个实例。此时下方将出现 References,显示该对象的每个引用。 或者,点击实例名称旁的箭头以查看其所有字段,然后点击一个字段名称查看其所有引用。 如果您要查看某个字段的实例详情,右键点击该字段并选择 Go to Instance
  3. References 标签中,如果您发现某个引用可能在泄漏内存,则右键点击它并选择 Go to Instance。 这将从堆转储中选择对应的实例,显示您自己的实例数据。

默认情况下,堆转储不会向您显示每个已分配对象的堆叠追踪。 要获取堆叠追踪,在点击 Dump Java heap 之前,您必须先开始记录内存分配。然后,您可以在 Instance View 中选择一个实例,并查看 Call Stack 标签以及 References 标签,如下图所示。不过,在您开始记录分配之前,可能已分配一些对象,因此,调用堆栈不能用于这些对象。包含调用堆栈的实例在图标 上用一个“堆栈”标志表示。(遗憾的是,由于堆叠追踪需要您执行分配记录,因此,您目前无法在 Android 8.0 上查看堆转储的堆叠追踪。)

默认情况下,堆转储不会向您显示每个已分配对象的堆叠追踪。 要获取堆叠追踪,在点击 Dump Java heap 之前,您必须先开始记录内存分配。然后,您可以在 Instance View 中选择一个实例,并查看 Call Stack 标签以及 References 标签,如下图所示。不过,在您开始记录分配之前,可能已分配一些对象,因此,调用堆栈不能用于这些对象。包含调用堆栈的实例在图标 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 上用一个“堆栈”标志表示。(遗憾的是,由于堆叠追踪需要您执行分配记录,因此,您目前无法在 Android 8.0 上查看堆转储的堆叠追踪。)

在您的堆转储中,请注意由下列任意情况引起的内存泄漏:

  • 长时间引用 Activity、Context、View、Drawable 和其他对象,可能会保持对 Activity 或 Context 容器的引用。
  • 可以保持 Activity 实例的非静态内部类,如 Runnable。
  • 对象保持时间超出所需时间的缓存。

捕获堆转储需要的持续时间标示在时间线中,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在类列表中,您可以查看以下信息:

  • Heap Count: 堆中的实例数。
  • Shallow Size: 此堆中所有实例的总大小(以字节为单位)。
  • Retained Size: 为此类的所有实例而保留的内存总大小(以字节为单位)。

在类列表顶部,您可以使用左侧下拉列表在以下堆转储之间进行切换:

  • Default heap: 系统未指定堆时。
  • App heap: 您的应用在其中分配内存的主堆。
  • Image heap: 系统启动映像,包含启动期间预加载的类。 此处的分配保证绝不会移动或消失。
  • Zygote heap: 写时复制堆,其中的应用进程是从 Android 系统中派生的。

默认情况下,此堆中的对象列表按类名称排列。 您可以使用其他下拉列表在以下排列方式之间进行切换:

  • Arrange by class: 基于类名称对所有分配进行分组。
  • Arrange by package: 基于软件包名称对所有分配进行分组。
  • Arrange by callstack: 将所有分配分组到其对应的调用堆栈。此选项仅在记录分配期间捕获堆转储时才有效。即使如此,堆中的对象也很可能是在您开始记录之前分配的,因此这些分配会首先显示,且只按类名称列出。

默认情况下,此列表按 Retained Size 列排序。 您可以点击任意列标题以更改列表的排序方式。

在 Instance View 中,每个实例都包含以下信息:

  • Depth: 从任意 GC 根到所选实例的最短 hop 数。
  • Shallow Size: 此实例的大小。
  • Retained Size: 此实例支配的内存大小(根据 dominator 树))。
将堆转储另存为 HPROF

在捕获堆转储后,仅当分析器运行时才能在 Memory Profiler 中查看数据。 当您退出分析会话时,您将丢失堆转储。 因此,如果您要保存堆转储以供日后查看,可通过点击时间线下方工具栏中的 Export heap dump as HPROF file 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传,将堆转储导出到一个 HPROF 文件中。 在显示的对话框中,确保使用 .hprof 后缀保存文件。

然后,通过将此文件拖到一个空的编辑器窗口(或将其拖到文件标签栏中),您可以在 Android Studio 中重新打开该文件。

要使用其他 HPROF 分析器(如 jhat),您需要将 HPROF 文件从 Android 格式转换为 Java SE HPROF 格式。 您可以使用 android_sdk/platform-tools/ 目录中提供的 hprof-conv 工具执行此操作。 运行包括以下两个参数的 hprof-conv 命令:原始 HPROF 文件和转换后 HPROF 文件的写入位置。 例如:

hprof-conv heap-original.hprof heap-converted.hprof

分析内存的技巧

使用 Memory Profiler 时,您应对应用代码施加压力并尝试强制内存泄漏。 在应用中引发内存泄漏的一种方式是,先让其运行一段时间,然后再检查堆。 泄漏在堆中可能逐渐汇聚到分配顶部。 不过,泄漏越小,您越需要运行更长时间的应用才能看到泄漏。

您还可以通过以下方式之一触发内存泄漏:

  • 将设备从纵向旋转为横向,然后在不同的 Activity 状态下反复操作多次。 旋转设备经常会导致应用泄漏 ActivityContextView 对象,因为系统会重新创建 Activity,而如果您的应用在其他地方保持对这些对象之一的引用,系统将无法对其进行垃圾回收。
  • 处于不同的 Activity 状态时,在您的应用与另一个应用之间切换(导航到主屏幕,然后返回到您的应用)。

提示: 您还可以使用 monkeyrunner 测试框架执行上述步骤。

利用 Network Profiler 检查网络流量

Network Profiler 能够在时间线上显示实时网络活动,包括发送和接收的数据以及当前的连接数。 这便于您查看应用传输数据的方式和时间,并据此对底层代码进行适当优化。点击 Android Profiler 窗口中的 NETWORK 时间线中的任意位置即可打开 Network Profiler

为什么应分析应用的网络活动

当您的应用向网络发出请求时,设备必须使用高功耗的移动或 WLAN 无线装置来收发数据包。无线装置不仅要消耗电力来传输数据,还需要消耗额外的电力来开启并且不锁定屏幕。

使用 Network Profiler,您可以查找频繁出现的短时网络活动峰值,这意味着您的应用需要经常打开无线装置,或需要长时间不锁定屏幕以处理集中出现的大量短时请求。这种模式说明您可以通过批量处理网络请求,减少必须开启无线装置来发送或接收数据的次数,从而优化应用,改善电池续航表现。这种方式还能让无线装置调整到低能耗模式,延长批量处理请求之间的间隔时间,节省能耗。

要详细了解优化应用网络活动 的相关技巧,请参阅减少网络耗电量

Network Profiler 概览

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

Android进阶核心笔记

百万年薪必刷面试题

最全Android进阶学习视频

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
片转存中…(img-KW3l4F3l-1712821201268)]

百万年薪必刷面试题

[外链图片转存中…(img-7YSGuGOb-1712821201268)]

最全Android进阶学习视频

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-YLTYnX57-1712821201268)]

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值