Andoid性能分析-内存
随着移动技术的发展,仅仅是完成功能早已是满足不了现有的需求了,除了产品设计,应用的操作体验、流畅度也成了留住用户的很重要的一方面。
应用的一些性能指标
- 内存
- CPU
- GPU
- 网络
针对应用的性能的优化,Android Studio也在逐渐完善自己的性能分析工具-Android Profiler,除此之外还有eclipse提供的一个分析工具MAT,这次我们只关注内存方面的性能优化。
为什么需要分析应用内存
Android 提供一个托管内存环境—当它确定您的应用不再使用某些对象时,垃圾回收器会将未使用的内存释放回堆中。 虽然 Android 查找未使用内存的方式在不断改进,但对于所有 Android 版本,系统都必须在某个时间点执行垃圾回收,Stop-the-world。这个大多数情况下不会被感知到。 但是如果应用分配内存的速度比系统回收内存的速度快,则当收集器释放足够的内存以满足分配需要时,应用可能会卡顿延迟,可能会导致应用跳帧,并使系统明显变慢。即使应用不会表现出变慢,但如果存在内存泄漏,即使应用进入后台运行也不会释放。 因此会强制执行不必要的垃圾回收操作,因而拖慢系统的内存性能。 最后,系统被迫终止应用进程以回收内存。
Android Profiler
要打开 Android Profiler 窗口,请按以下步骤操作:
- 点击 View > Tool Windows > Android Profiler(也可以点击工具栏中的 Android Profiler )。
- 在 Android Profiler 窗口顶部,选择您想要分析的设备和应用进程。
启用高级分析
要显示高级分析数据,Android Studio 必须在您编译后的应用中插入监控逻辑。 高级分析工具提供的功能包括:
- Event 时间线(所有分析器窗口中均有)
- 分配对象数量(Memory Profiler 中)
- 垃圾回收 Event(Memory Profiler 中)
- 有关所有传输的文件的详情(Network Profiler 中)
要启用高级分析,可以按以下步骤操作:
- 选择 Run > Edit Configurations。
- 在左侧窗格中选择您的应用模块。
- 点击 Profiling 标签,然后勾选 Enable advanced profiling。
内存计数类别
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++ 中分配的对象。
查看内存分配
- 浏览列表以查找堆计数异常大且可能存在泄漏的对象。 为帮助查找已知类,点击 Class Name 列标题以按字母顺序排序。 然后点击一个类名称。 此时在右侧将出现 Instance View 窗格,显示该类的每个实例。
- 在 Instance View 窗格中,点击一个实例。 此时下方将出现 Call Stack 标签,显示该实例被分配到何处以及哪个线程中。
- 在 Call Stack 标签中,点击任意行以在编辑器中跳转到该代码。
MAT
Overview
主要显示内存的分配,彩色区域为消耗的内存,灰色区域为空闲的内存。
Leak Suspects
MAT会给出可能出现问题的地方,点击detail查看详情,不过个人感觉用处不大。
Histogram
在Histogram中有四列数据
- Class Name:类名
- Objects :堆中的实例数
- Shallow Heap : 此堆中所有实例的总大小
- Reained Heap: 为此类的所有实例而保留的内存总大小
同样在菜单栏中也可以选择设置列表的显示方式,个人比较习惯用package的方式,方便查看应用中哪些类可能泄露了。另外在顶部可以搜索想要查看的类.
Dominator Tree
在上面提到了Reained Heap,另一种解释是一个对象的Retained Set所包含对象所占内存的总大小,那什么是一个对象的Retained Set
什么可以作为GC Root?