0%

性能优化-:(02)2022.1.16-性能优化第二次课

LeakCanary 只能在线下,不能用于线上。LeakCanary 有什么缺点?线上怎么做?

只能对 Acitvirty 和 Fragment 去做

强引用:宁愿 OOM 也不会回收的

软引用:内存足够的时候,即时发生GC,也不会被回收,但是内存不足的时候,就回收了

一、OOM 与内存优化

启动优化,APM 框架

日志系统,使用 mmap 系统崩了也不会丢

使用 xlog

Linux 内核动态内存分配,所以 MemAvailable 不一定准确

RSS 实际使用的物理内存——包含了 共享库的内存(so动态链接库),所以容易误导

python 做自动化测试,python 不断读取那些数据

Android 会对所有进程分类,每一个类别都有其 oom_adj 的值取值范围, oom_adj 的值越大,说明越不重要。因此,内存不足 kill 进程时,从 oom_adj 高的进程开始杀

如果想要一个服务长期运行,应该将其运行在单独的进程里,即 UI进程与 Service 进程分离,这样就能获得较小的 oom_adj 值,就容易存活。而占有大量内存的 UI 进程会分类为 Cached 进程,能够在需要的时候更快地被回收。

LeakCanary 的源码

里面注册了 ContentProvider ,为啥?

线上监测

  • 端上解析:就是在设备上做引擎解析,自己解析内存泄漏

  • 后台解析: 内存镜像,fork 出当前进程,然后将子进程信息发给后台

监测 Activity 生命周期可以使用 RegisterActivityLifecycleCallback 的方式,然后使用 WeakHashMap 来监测回收,因为 WeakHashMap 它的 Key 是弱引用,它里面有个 ReferenceQueue 。

在 ActivityLifecycleCallback 的 onActivityDestroy 回调中,以 Activity 的方式作为 key ,value 可以使用 activity.getClass().getSimpleName(),在 WeakHashMap 中就可以监听 key 的回收,就能监听 Activity 的回收了。类似于如下代码:

1
WeakHashMap<Activity, String> datas = 。。。

然后,在 onActivityStopped 回调中,因为 activity 此时不可见了,可以使用 GC 来找泄漏的 Activity :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void onActivityStopped(){
//申请一个大的 byte 数组,便于后续的 GC 触发
byte[] bytes = new byte[N];
//延时
SystemClock.sleep(100);
//GC,使用 runtime的gc 更容易触发 gc 一点
Runtime.getRuntime().gc();
//课程里面说用这个来复活,而不是直接用上面的 gc ,没看懂意思,后续深究
//System.runFinalization();

//从之前的 WeakHashMap 中遍历所有的 Activity

//分析内存
Debug.MemoryInfo debug = new Debug.MemoryInfo();
Debug.getMemoryInfo(debug);
//就可以获取很多内存信息了
int nativePss = debug.nativePss() >> 10;
}

当然,这里面还需要很多判断,比如判断 Activity 是否在后台。有个同学提出了,如果面试官说这里每次 Activity 的 onStop 都去做这些操作,是否合理?那也确实不合理,假如,只是做了 Activity a 跳转到 Activity b,触发了 a 的 onStop ,这里就有点浪费。所以呢,这里还需要判断 ,其实也是判断 Activity 是否在后台(可能不一定对,听课是这样理解说判断是否在后台)。

这里获取 pss 也能生成曲线图,这个曲线图有什么用呢?就是监测在运行某个功能时,内存占用的问题,就能定向排查问题

爱奇艺的 xhook ,用于 nativeHook

路哥性能优化课程的产出:

  1. 启动优化框架

  2. 简单的 APM 框架

谢谢你的鼓励