Android 启动优化

2019-03-01  本文已影响0人  34sir

优化工具

systrace + 函数插桩 可以看到系统的一些关键信息 比如GC System Server CPU调度
可以通过下面指令查看收集支持的systrace类型 比如Dalvik sched ss app

python systrace.py --list-categories

将下面的两个函数分别插入到每个方法的出口和入口 实现插桩 通过它可以看到主线程和其他线程中函数的调用过程

class Trace {
  public static void i(String tag) {
    Trace.beginSection(name);
  }


  public static void o() {
      Trace.endSection();
  }
}

怎么做?

1⃣️ 控制线程的数量 要有统一的线程池(根据性能控制线程数量)
线程切换的数据可以通过sched文件查看

proc/[pid]/sched:
  nr_voluntary_switches:     
  主动上下文切换次数,因为线程无法获取所需资源导致上下文切换,最普遍的是 IO。    
  nr_involuntary_switches:   //需要特别关注此值
  被动上下文切换次数,线程被系统强制调度导致上下文切换,例如大量线程在抢占 CPU。

2⃣️ 检查线程池间的锁
对于可以并发的任务 可以通过线程池最大程度的提升启动速度 避免出现如下主线程空转2950mm的情况


主线程空转.png
python systrace.py dalvik -b 90960 -a com.sample.gc

监控启动过程中GC的总耗时的情况以及阻塞式同步GC的耗时:

// GC 使用的总耗时,单位是毫秒
Debug.getRuntimeStat("art.gc.gc-time");
// 阻塞式 GC 的总耗时
Debug.getRuntimeStat("art.gc.blocking-gc-time");

如果发现主线程出现比较多的同步GC等待 还需要通过Alloation工具做进一步分析
启动过程应该避免出现大量的字符串操作 尤其是序列化与反序列化 复用频繁操作的对象 Native实现一定需要频繁创建的对象 对象的逃逸也容易引起GC问题 应该保证对象的生命周期足够短 在栈上就销毁
关于对象逃逸:
new 操作产生的对象并不一定分配在堆中 JVM通过对象逃逸分析分析出对象的引用的使用你范围从而判断是否要在堆中分配 没有发生逃逸则分配在栈上 一般此对象当成返回值返回则可以视为逃逸

class GetClassLoader extends PathClassLoader {
    public Class<?> findClass(String name) {
        // 将 name 记录到文件
        writeToFile(name,"coldstart_classes.txt");
        return super.findClass(name);
    }
}

然后通过 ReDexInterdex调整类在 Dex 中的排列顺序 最后可以利用 010 Editor 查看修改后的效果

// Dalvik Globals.h
gDvm.classVerifyMode = VERIFY_MODE_NONE;
// Art runtime.cc
verify_ = verifier::VerifyMode::kNone;

总结

我们可以从 业务梳理 线程优化 GC优化 系统调用优化 I/O优化 类重排 资源文件重排 这几个角度着手优化

上一篇 下一篇

猜你喜欢

热点阅读