Android启动优化之精确测量启动各个阶段的耗时

1. 直观地观察应用启动时长

我们可以通过观察logcat日志查看Android应用启动耗时,过滤关键字"Displayed":
ActivityTaskManager: Displayed com.peter.viewgrouptutorial/.activity.DashboardActivity: +797ms
启动时长(在这个例子中797ms)表示从启动App到系统认为App启动完成所花费的时间。

2. 启动时间包含哪几个阶段

从用户点击桌面图标,到Activity启动并将界面第一帧绘制出来大概会经过以下几个阶段。

  1. system_server展示starting window
  2. Zygote fork Android 进程
  3. ActivityThread handleBindApplication(这个阶段又细分为)
    • 加载程序代码和资源
    • 初始化ContentProvider
    • 执行Application.onCreate()
  4. 启动Activity(执行 onCreate、onStart、onResume等方法)
  5. ViewRootImpl执行doFrame()绘制View,计算出首帧绘制时长。
    流程图如下:
    在这里插入图片描述
    我们可以看出:阶段1和2都是由系统控制的。App开发者对这两个阶段的耗时能做的优化甚微。

    3. 系统是如何测量启动时长的?


    本文源码基于android-30
    我们在cs.android.com源码阅读网站上全局搜索
    在这里插入图片描述
    1.在ActivityMetricsLogger.logAppDisplayed()方法中发现了打印日志语句
private void logAppDisplayed(
  TransitionInfoSnapshot info
) {
   
   
    if (info.type != TYPE_TRANSITION_WARM_LAUNCH && info.type != TYPE_TRANSITION_COLD_LAUNCH) {
   
   
        return;
    }
    EventLog.writeEvent(WM_ACTIVITY_LAUNCH_TIME,
            info.userId, info.activityRecordIdHashCode, info.launchedActivityShortComponentName,
            info.windowsDrawnDelayMs);
    StringBuilder sb = mStringBuilder;
    sb.setLength(0);
    sb.append("Displayed ");
    sb.append(info.launchedActivityShortComponentName);
    sb.append(": ");
    TimeUtils.formatDuration(info.windowsDrawnDelayMs, sb);
    Log.i(TAG, sb.toString());
}
  1. TransitionInfoSnapshot.windowsDrawnDelayMs是启动的时长。它在以下方法中被赋值:
    • ActivityMetricsLogger.notifyWindowsDrawn()
    • ➡️ TransitionInfo.calculateDelay()
//ActivityMetricsLogger.java
TransitionInfoSnapshot notifyWindowsDrawn(
  ActivityRecord r, 
  long timestampNs
) {
   
     
  TransitionInfo info = getActiveTransitionInfo(r);
  info.mWindowsDrawnDelayMs = info.calculateDelay(timestampNs);
  return new TransitionInfoSnapshot(info);
}
private static final class TransitionInfo {
   
   
 int calculateDelay(long timestampNs) {
   
   
   long delayNanos = timestampNs - mTransitionStartTimeNs;
   return (int) TimeUnit.NANOSECONDS.toMillis(delayNanos);
 }
}
  1. timestampNs表示启动结束时间,mTransitionStartTimeNs表示启动开始时间。它们分别是在哪赋值的呢?
    mTransitionStartTimeNs启动开始时间在notifyActivityLaunching方法中被赋值。调用堆栈如下:
    • ActivityManagerService.startActivity()
    • ➡️ActivityManagerService.startActivityAsUser()
    • ➡️ActivityStarter.execute()
    • ➡️ActivityMetricsLogger.notifyActivityLaunching()
    在这里插入图片描述
    ActivityMetricsLogger.notifyActivityLaunching(…)
//ActivityMetricsLogger.java
private LaunchingState notifyActivityLaunching(
  Intent intent,
  ActivityRecord caller,
  int callingUid
) {
   
   
  ...
  long transitionStartNs = SystemClock.elapsedRealtimeNanos(
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值