Android 耗时分析(adb shell/Studio CPU Profiler/插桩Trace API)

1.adb logcat 查看冷启动时间和Activity显示时间:

过滤Displayed关键字,可看到Activity的显示时间
在这里插入图片描述
那上面display后面的是时间是指包含哪些过程的时间呢?

模拟在Application中沉睡1秒操作,冷启动情况下:
在这里插入图片描述
从上可知:在冷启动情况下,第一个activity的display是冷启动的总时间=application+Activity的时间。

接着,界面上点击按钮,随意启动一个Activity:
在这里插入图片描述
从上可知:app进程在线情况下,启动activity的display 时间才是activity的显示时间(onCreate()->onStart()->onResume())

2.adb shell 启动activity的时间

格式:

adb shell am start -W package名/包名路径的activity

例如,执行打开指定的mainActivity,如下图所示:
在这里插入图片描述
解读以上数据

  • TotalTime: 是Activity的启动时间 ,与adb logcat 中Display 时间规则一致(通常以这个时间为准)
  • WaitTime: 是AMS启动Activity的总耗时(它会TotalTime更大,存在跨进程通讯回执时间)

通过adb shell 启动的activity 必须具备以下条件之一:

设置程序的主入口:
在这里插入图片描述
或者设置exported为true
在这里插入图片描述

3.AndroidStudio的cpu Profile:

3.1适用于app冷启动时的trace捕捉

创建一个新的运行configurations, 在profiling中配置:
在这里插入图片描述
一般是选择 java method sample,即Profiler的sample 模式,对性能影响小。系统会间隔us周期性记录java方法的调用栈,记录较为耗时,耗时较少不会显示在trace中。

  • Java method trace: 适用于精确记录方法执行时间,即profiler的instrument模式,因一直记录方法的调用栈和cpu 使用情况,对性能影响很大,可能会造成黑屏,卡顿等情况。
  • CallStack sample 适用于记录natvie+java的方法分析,Profiler的sample 模式。
  • System trace: 记录同一个过程中系统各个进程的trace,适合更复杂的分析耗时。

使用方式: 先使用java method sample 记录,找出耗时的所在;接着,再用 java method trace 精确分析真正的耗时时间。

点击profiler 按钮后,等待安装后,启动后,会自动开始捕捉,等执行完需要观察的流程后,点击stop 。

在这里插入图片描述
打开录制的trace文件,选择main 主线程,打开如下所示:

在这里插入图片描述
从上面,可以清楚看到app 主线程中每个环节的方法调用栈和耗时时间等。 带颜色的方块越长,耗时越多,绿色一般是app中的代码。

选择Application的onCreate()查看,双击该方法,出现如下所示:

在这里插入图片描述
通过上图,可知左边菜单可知该方法耗时1s ,右边菜单top down 可知该方法的调用栈,真正耗时所在,沉睡一秒导致。

3.2 app 运行时,记录trace

有些界面是在app 特殊情况下触发,捕获该流程的trace 。可通过usb 连接手机,其次,在profiler 界面中选择可debug的进程,如下图所示:
在这里插入图片描述
选择cpu ,双击,如下所示:
在这里插入图片描述
在这里插入图片描述
也可以自由配置记录条件,选择不同缓存大小和周期时间us。

选择需要记录的trace类型,然后在app中使用流程,点击stop 。比如,打开一个视频页面,想了解其播放过程的耗时,如下所示:

在这里插入图片描述
从top down 中可清楚看到,视频页面中播放视频testPlay()的调用时间。

4.插桩使用Debug#trace api 精准记录方法执行时间

插桩方式,在release和debug 包下都可以使用,比较灵活方便。

由于存在 8MB 的缓冲区空间限制,因此 Debug API 中的 startMethodTracing(String tracePath) 方法专为时间间隔较短或难以手动启动/停止记录的场景而设计。如需设置持续时间更长的记录,请使用 Android Studio 中的性能剖析器界面。

简而言之,这种方式适合app冷启动,或者短时间内的方法记录trace。

public class TraceMethodUtils {
    /**
     * 适合于非常精确的记录,某个具体函数的耗时分析
     *
     * profiler cpu 中instrument模式,会从开始一直记录方法/cpu 使用情况,对性能影响大。
     */
    public static void  startTrack(String tracFileName){
        Debug.startMethodTracing(fixTraceFileName(tracFileName));
    }

    /**
     *  在android 5.0 以后使用,间隔时间微妙 
     *
     *  profiler cpu 中sample模式,系统间隔us 周期性记录调用栈,对性能影响小
     * @param tracFileName
     */
    public static void startSampleTrack(String tracFileName){
        //1000us=1ms 周期性记录一次
        Debug.startMethodTracingSampling(fixTraceFileName(tracFileName),0,1000);
    }
    private static String fixTraceFileName(String tracFileName){
        if (!TextUtils.isEmpty(tracFileName)){
            tracFileName=tracFileName.endsWith(".trace")?tracFileName:tracFileName+".trace";
            tracFileName=new StringBuilder().append(System.currentTimeMillis()).append("_").append(tracFileName).toString();
        }else{
            tracFileName=new StringBuilder().append(System.currentTimeMillis()).append(".trace").toString();
        }
        return tracFileName;
    }
    /**
     * 结束跟踪
     */
    public static void stopTrack(){
        Debug.stopMethodTracing();
    }
}

冷启动/界面启动的分析,推荐使用startSampleTrack()。

这里,具体分析某个方法testPlay(), 执行需要记录的方法,记录如下所示:
在这里插入图片描述
以上文件在在DeviceFileExplorer 窗口中sdcard/android/data/package名目录,双击打开该trace文件,如下所示:
在这里插入图片描述
使用方式:首先选择需要查看的线程,进行双击进入。因testPlay()是在主线程中执行,因此在这里选择主线程:
在这里插入图片描述
Bottom UP窗口

用于观察某个方法中,调用其他若干方法的耗时占比,可更进一步筛选出耗时的具体位置,选择查看比例排前的几个方法。
比如,选中testPlay(),查看其内部的耗时方法占比:创建VideoView对象,耗时最大,3002us微妙=3ms毫秒。

在这里插入图片描述

Flame chat 火焰图窗口

用于倒置查看某个方法中调用若干方法的查看,很直观的看到方法调用情况与耗时情况。淡黄色的往往是需要关注的方法点,可优化点也是在这里。

在这里插入图片描述
Top Down窗口

可用于查看,该方法向下调用栈,也可以清楚看到接下来代码逻辑走向。也是按耗时排列。

在这里插入图片描述
使用总结: 打开trace文件后–>双击选择线程–>选择观察的方法–>Top Down窗口细化查看耗时方法–>Bottom UP窗口找到耗时所在点。

Trace 存储路径和sdcard 权限问题

简单来看下trace的保存路径逻辑:
在这里插入图片描述

发现,trace 是默认保存在sdcard/android/data/package名目录或者sdcard根目录中,因此必须要有sdcard读写权限。trace会自动补全.trace后缀名。

官方资料:https://developer.android.com/studio/profile/record-traces?hl=zh-cn#debug-api

资料参考

  • Android Studio 中 CPU Profiler 系统性能分析工具的使用:https://juejin.cn/post/7098548053136637983
  • https://juejin.cn/post/7024387231104106503
  • 基于AOP思想的Android方法耗时开源分析工具TimeTracer:https://www.paincker.com/time-tracer/
  • https://jishuin.proginn.com/p/763bfbd4c428
  • https://zhuanlan.zhihu.com/p/508526020
  • https://juejin.cn/post/7163522788781719559
  • 性能优化:https://www.jianshu.com/p/837ad55f3049

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/46601.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot 集成 Elasticsearch

一、版本 spring-boot版本:2.3.7.RELEASEElasticsearch7.8.0版本说明详见 二、Elasticsearch 下载和安装 Elasticsearch 下载 kibana下载 ik分词器下载 配置IK分词器 2.1 解压,在elasticsearch-7.8.0\plugins 路径下新建ik目录 2.2 将ik分词器解压放…

pytest---环境切换(base-url)

前言 前面小编介绍了如何通过pytest的插件来实现自动化测试的环境的切换,当时使用的方法是通过钩子函数进行获取命令行参数值,然后通过提前配置好的参数进行切换测试环境地址,今天小编再次介绍一种方法,通过pytest的插件&#xff…

2023年深圳杯数学建模B题电子资源版权保护问题

2023年深圳杯数学建模 B题 电子资源版权保护问题 原题再现: 版权又称著作权,包括发表权、署名权、修改权、保护作品完整权、复制权、发行权、出租权、展览权、表演权、放映权、广播权、信息网络传播权、摄制权、改编权、翻译权、汇编权及应当由著作权人…

安全学习DAY06_抓包技术-HTTPHTTPS

抓包技术-HTTP&HTTPS HTTP&HTTPS抓包针对Web&APP&小程序&PC应用等 本节目的: 掌握几种抓包工具证书安装操作掌握几种HTTP&HTTPS抓包工具的使用学会Web,APP,小程序,PC应用等抓包了解本节课抓包是针对哪些…

【100天精通python】Day17:常见异常类型与解决,异常处理语句

目录 一 python 的常见异常类型与解决 二 常用的异常处理语句 1 try...except语句 2 try...except...else语句 3 try...except...finally语句 4 使用raise语句抛出异常 5 自定义异常类型 6 异常链处理 在 Python中,异常是在程序运行时发生的错误或意外情…

华为eNSP:路由引入

一、拓扑图 二、路由器的配置 1、配置路由器的IP AR1: [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [Huawei-GigabitEthernet0/0/0]qu AR2: [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.2 24 [Huaw…

【Lua学习笔记】Lua进阶——函数和闭包

文章目录 函数函数嵌套闭包Closures可变函数函数重载 函数 函数嵌套 function A()print("这里是函数A")return function ()print("返回函数不要起名")end end B A() B()输出: 这里是函数A 返回函数不要起名使用函数嵌套的用法,我…

power dns recursor 4.5以后版本的奇葩问题

问题 最近升级了 pdns-recursor 从 4.1.X 升级至 4.8.x 出现下面问题 效果为 nslookup 可以返回 ip 地址 dig 无法返回对应 ip 地址 ad dns 服务器转发过来的解析都不响应 tcp 抓包如下 当使用 nslookup 请求时 addition rrs 请求为 0 当使用 dig 请求时 addition rrs 请求为 1…

Java虚拟机——Java内存模型

"Java内存模型"来屏蔽各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。主要目的:定义程序中各种变量的访问规则,即关注在虚拟机中把变量值存储到内存和从内存中取出变量值这样的底层细…

用 Node.js 手写 WebSocket 协议

目录 引言 从 http 到 websocekt 的切换 Sec-WebSocket-Key 与 Sec-WebSocket-Accept 全新的二进制协议 自己实现一个 websocket 服务器 按照协议格式解析收到的Buffer 取出opcode 取出MASK与payload长度 根据mask key读取数据 根据类型处理数据 frame 帧 数据的发…

使用Python搭建代理服务器- 爬虫代理服务器详细指南

搭建一个Python爬虫代理服务器可以让你更方便地管理和使用代理IP。下面是一个详细的教程来帮助你搭建一个简单的Python爬虫代理服务器: 1. 首先,确保你已经安装了Python。你可以在官方网站(https://www.python.org/)下载并安装最新版本的Python。 2. 安…

一.MySQL的主从复制

目录 一.MySQL的主从复制 1.2主从复制的工作过程和原理 1.2.1主从复制工作过程为两日志和三线程 ​编辑 1.2.2主从复制的工作原理 1.3主从复制延迟的原因 1.4主从复制的架构 1.5.MySQL四种同步方式 1.5.1异步复制(Async Replication) 1.5.2 同步复制(Sync Re…

新功能 – Cloud WAN:托管 WAN 服务

我很高兴地宣布,我们推出了 Amazon Cloud WAN,这是一项新的网络服务,它可以轻松构建和运营连接您的数据中心和分支机构以及多个 Amazon 区域中的多个 VPC 的广域网(WAN)。 亚马逊云科技开发者社区为开发者们提供全球的…

Linux centos7.x系统 下没有ens33 网卡的解决方案

一、背景 安装完windows11 Centos7.9 版本的双系统之后 , 启动Centos7.9时发现没有网卡信息 , 只有ifcfg-lo网卡的信息 , 这个时候就证明没有网卡信息,或者网卡驱动不匹配(我这里是没有网卡),所以我们要重新安装 , 安装步骤如下 : 二、安装步骤 1.查…

使用分布式HTTP代理爬虫实现数据抓取与分析的案例研究

在当今信息爆炸的时代,数据已经成为企业决策和发展的核心资源。然而,要获取大规模的数据并进行有效的分析是一项艰巨的任务。为了解决这一难题,我们进行了一项案例研究,通过使用分布式HTTP代理爬虫,实现数据抓取与分析…

C++多线程编程(第二章 多线程通信和同步)

1、多线程状态 1.1线程状态说明 初始化(Init):该线程正在被创建; 就绪(Ready):该线程在就绪列表中,等待CPU调度; 运行(Running):该线程正在运行; 阻塞&…

吉林大学计算机软件考研经验贴

文章目录 简介政治英语数学专业课 简介 本人23考研,一战上岸吉林大学软件工程专硕,政治72分,英一71分,数二144分,专业课967综合146分,总分433分,上图: 如果学弟学妹需要专业课资料…

Pytorch个人学习记录总结 07

目录 神经网络-非线性激活 神经网络-线形层及其他层介绍 神经网络-非线性激活 官方文档地址:torch.nn — PyTorch 2.0 documentation 常用的:Sigmoid、ReLU、LeakyReLU等。 作用:为模型引入非线性特征,这样才能在训练过程中…

leetcode 852. Peak Index in a Mountain Array(峰值索引)

一个数组保证是峰值数组(存在一个值大于左边和右边部分数组),找出峰值的index。 要求时间复杂度在O(logn)。 思路: 时间复杂度为O(logn), 可以想到用binary search. 其实用O(n)的找最大值也能通过。 public int peakIndexInMou…

Spring Boot 拦截器实现:登录验证 统一异常处理 返回数据规范化

学习 Spring 和 servlet 初期,我们在判断用户身份时,都是在每个方法中获取会话、获取对象,这种方式冗余度高,增加代码复杂度,维护成本也高,因此想到可以使用 AOP 来实现一个公共的方法,这个公共…