测量 Android 应用程序启动时间的最精确方法是什么?
启动时间是指 2. 和 3. 之间的差异:
- 应用程序进程未运行
- 用户单击启动器中的应用程序图标
- Main Activity 已完全初始化
所以我基本上需要以某种方式获取自 JVM 启动以来经过的时间并记录它。
测量 Android 应用程序启动时间的最精确方法是什么?
启动时间是指 2. 和 3. 之间的差异:
所以我基本上需要以某种方式获取自 JVM 启动以来经过的时间并记录它。
我知道我来不及回答,但是,这恰恰回答了这个问题。
对于 API 版本 19 或更高版本,此信息默认记录在 Logcat 上。
从 Android 4.4(API 级别 19)开始,logcat 包含一个输出行,其中包含一个名为 Displayed 的值。该值表示从启动进程到完成在屏幕上绘制相应活动之间经过的时间量。
ActivityManager:显示 com.android.myexample/.StartupTiming:+3s534ms
关键是找对地方——
如果您从命令行或终端中跟踪 logcat 输出,则查找经过的时间很简单。要在 Android Studio 中查找经过的时间,您必须在 logcat 视图中禁用过滤器。禁用过滤器是必要的,因为系统服务器而不是应用程序本身提供此日志。
摘录来自文档。
我会将您的问题解释为“我的应用程序启动时间是否足够快。我怎样才能检查我已经做了我能做的一切?
启动时间在很大程度上是一个错误的指标,因为它会因设备和 ROM 而异。我猜您最可能感兴趣的是您的代码有多少需要很长时间才能执行,以及什么可能会阻塞主线程。
我发现最有效的方法是在应用程序启动时使用Traceview,然后查看该方法执行所需的时间以及主线程上是否存在任何间隙。
开始追踪:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Debug.startMethodTracing("startup");
}
}
停止追踪:
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Debug.stopMethodTracing();
}
收集跟踪后,您应该能够看到对启动时间有重大影响的任何事情。在我的例子中,如下所示,UI 线程上被阻塞的地方有很大的差距。
事实证明,Crashlytics 和 Coremetrics 都需要调用randomUUID()
,然后跨线程同步并阻塞主线程。解决方案只是启动一个新线程来初始化 Coremetrics 代码。
这是我仅通过测量启动时间就无法获得的东西,但它实际上将应用程序的“启动时间”加快了几百毫秒。
这是分离 Coremetrics 初始化的单独线程后的另一个快照:
按以下方式检查 adb shell。
adb shell
adb logcat -b events | grep am_activity_launch_time
[Output]
01-01 12:32:53.469 1236 1262 I am_activity_launch_time:
[0,205360373,com.sec.android.app.clockpackage/.ClockPackage,378,**378**,0]
Remarks:
Launch time for Clock is 378ms.
将整个onCreate()
方法包装在一个TimingLogger
. 把这个放在开头:
TimingLogger timings = new TimingLogger(TAG, "methodA");
最后是:
timings.dumpToLog();
如果您想在某个中间步骤减少时间,您可以timings.addSplit("name");
获取到达该步骤所需的时间。
可以使用以下代码实现时间跟踪:
覆盖你的Application
:
public class CustomApplication extends Application {
public final static long APP_START_TIME = System.currentTimeMillis();
/**
* Do all other application stuff
*/
}
并在您的 main 中添加几行Activity
:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View contentView = findViewById(android.R.id.content);
contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
contentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
contentView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
long launchTime = System.currentTimeMillis() - CustomApplication.APP_START_TIME;
Log.e("TEST", "App launch time = " + launchTime);
}
});
}
}
并且不要忘记在以下位置定义您的自定义应用程序Manifest
:
<application
android:label="@string/app_name"
android:name=".CustomApplication" >
</application>
重要提示:您必须在启动前终止您的应用程序,因为应用程序存储了跟踪初始时间的静态变量。
在android中显示启动时间的简单方法。
有时,Displayed
logcat 输出中的行包含一个额外的总时间字段。例如:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
在这种情况下,第一次测量仅针对第一次绘制的活动
来源:初始显示时间
一种可能性是在onCreate()
方法开始和结束时保存时间,onCreate() method
然后将这些时间相互减去以获得初始化应用程序所花费的时间。