//Application.javapublicvoidonCreate(){super.onCreate();//在Application中使用postFrameCallbackChoreographer.getInstance().postFrameCallback(newFPSFrameCallback(System.nanoTime()));}publicclassFPSFrameCallbackimplementsChoreographer.FrameCallback{privatestaticfinalString TAG ="FPS_TEST";privatelong mLastFrameTimeNanos =0;privatelong mFrameIntervalNanos;publicFPSFrameCallback(long lastFrameTimeNanos){mLastFrameTimeNanos = lastFrameTimeNanos;mFrameIntervalNanos =(long)(1000000000/60.0);}@OverridepublicvoiddoFrame(long frameTimeNanos){//初始化时间if(mLastFrameTimeNanos ==0){mLastFrameTimeNanos = frameTimeNanos;}finallong jitterNanos = frameTimeNanos - mLastFrameTimeNanos;if(jitterNanos >= mFrameIntervalNanos){finallong skippedFrames = jitterNanos / mFrameIntervalNanos;if(skippedFrames>30){//丢帧30以上打印日志Log.i(TAG,"Skipped "+ skippedFrames +" frames! "+"The application may be doing too much work on its main thread.");}}mLastFrameTimeNanos=frameTimeNanos;//注册下一帧回调Choreographer.getInstance().postFrameCallback(this);}}
A8S:/ $ dumpsys cpuinfo
Load:1.12/1.12/1.09
CPU usage from 484321ms to184247ms ago (2022-11-0214:48:30.793to2022-11-0214:53:30.866):2%1053/scanserver:0.2% user +1.7% kernel0.6%934/system_server:0.4% user +0.1% kernel / faults:563 minor0.4%564/signserver:0% user +0.4% kernel0.2%256/ueventd:0.1% user +0% kernel / faults:320 minor0.2%474/surfaceflinger:0.1% user +0.1% kernel0.1%576/vendor.sprd.hardware.gnss@2.0-service:0.1% user +0% kernel / faults
:54 minor0.1%286/logd:0% user +0% kernel / faults:10 minor0.1%2821/com.allinpay.appstore:0.1% user +0% kernel / faults:1312 minor0.1%447/android.hardware.health@2.0-service:0% user +0% kernel / faults:1175 minor0%1855/com.smartpos.dataacqservice:0% user +0% kernel / faults:755 minor0%2875/com.allinpay.appstore:pushcore:0% user +0% kernel / faults:744 mino
r0%1191/com.android.systemui:0% user +0% kernel / faults:70 minor0%1774/com.android.nfc:0% user +0% kernel0%172/kworker/1:2:0% user +0% kernel0%145/irq/24-70900000:0% user +0% kernel0%575/thermald:0% user +0% kernel / faults:300 minor
...
4.Trace System Calls:捕获细粒度的详细信息,使您可以检查应用程序与系统资源的交互方式
您可以检查线程状态的确切时间和持续时间,可视化CPU瓶颈在所有内核中的位置,并添加自定义跟踪事件进行分析。在对性能问题进行故障排除时,此类信息可能至关重要。要使用此配置,您必须将应用程序部署到运行Android 7.0(API级别24)或更高版本的设备。
/*** Run the message queue in this thread. Be sure to call* {@link #quit()} to end the loop.*/
public static void loop() {...for (;;) {Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging = me.mLogging;if (logging != null) {// 1logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);}...try {// 2 msg.target.dispatchMessage(msg);dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;} finally {if (traceTag != 0) {Trace.traceEnd(traceTag);} }...if (logging != null) {// 3logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);}
在Looper的loop()方法中,在其执行每一个消息(注释2处)的前后都由logging进行了一次打印输出。可以看到,在执行消息前是输出的">>>>> Dispatching to “,在执行消息后是输出的”<<<<< Finished to ",它们打印的日志是不一样的,我们就可以由此来判断消息执行的前后时间点。
publicclassAppBlockCanaryContextextendsBlockCanaryContext{....../*** 指定判定为卡顿的阈值threshold (in millis), * 你可以根据不同设备的性能去指定不同的阈值** @return threshold in mills*/publicintprovideBlockThreshold(){return1000;}....}
自从Android引入 ART 并且在Android 5.0上成为默认的运行时之后,对象分配和垃圾回收(GC)造成的卡顿已经显著降低了,但是由于对象分配和GC有额外的开销,它依然又可能使线程负载过重。 在一个调用不频繁的地方(比如按钮点击)分配对象是没有问题的,但如果在在一个被频繁调用的紧密的循环里,就需要避免对象分配来降低GC的压力。