traceview android studio,TraceView 的正确打开方式

引言

TraceView 是 Android SDK 提供的一个性能分析工具官网介绍 ,一般用来检查 UI 卡顿、分析 app 耗时操作。但是对于大多说 Android 开发来说,TraceView 的图形化页面只能让人感觉一脸懵逼!!!

本文重点

昨天在干货集中营 发现这一篇文章 一个能让你了解所有函数调用顺序以及函数耗时的Android库(无需侵入式代码) 文里面提到可以使用 dmtracedump 命令把 trace 文件转为 txt ,然后再从 txt 里面提取我们需要的信息。

以上为本文全部主要内容,下面的啰嗦都是对以上内容的具体阐释。

获得 trace 文件

通过点击 DDMS start Method Profiling (第一次点击开始,第二次点击结束)

1e038ef2e586

traceview_picture_1.png

1e038ef2e586

traceview_picture_2.png

在代码中通过使用

android.os.Debug.startMethodTracing()

android.os.Debug.stopMethodTracing()

生成 traceView ,然后通过下面的 adb pull 命令导出 traceView

在 AndroidStudio 中获取,这个是本文重点,上面两种方式纯属为了凑数

点击 monitors cpu 模块的小闹钟(第一次点击开始,第二次点击结束)

1e038ef2e586

traceview_picture_3.png

然后 trace 文件会被存放在项目根目录的 captures 目录。

在项目根目录的 gradle 文件中增加一个 task

task AppOutPutMethodOrder() {

doLast {

def capturesDirPath = project.getProjectDir().path + File.separator + "captures";

def capturesDir = new File(capturesDirPath);

capturesDir.traverse {

if (it.isFile() && it.name.endsWith(".trace")) {

def orderName = it.name.replace("trace", "txt")

def orderFile = new File(capturesDirPath, orderName)

orderFile.write("")

def dmtracedumpDir = getDmtraceDumpDir();

//说明:dmtracedump 为 android sdk自带工具,要执行dmtracedump命令则需要先添加环境变量

def baseComand = dmtracedumpDir + "dmtracedump -ho " + it.absolutePath + " >> " + orderFile.absolutePath

println baseComand

String osNameMatch = System.getProperty("os.name").toLowerCase();

if (osNameMatch.contains("windows")) {

("cmd /c start /b " + baseComand).execute()

} else {

["bash", "-c", baseComand].execute()

}

}

}

}

}

执行命令

gradlew AppOutPutMethodOrder

利用 dmtracedump 命令把 trace 文件转为 txt 文件

1e038ef2e586

traceview_picture_4.png

txt 文件比较大,AndroidStudio 自带的文本阅读器打不开,需要用其他工具打开(这里使用的是 sublime Text)下面是截取的一部分 txt 内容

1e038ef2e586

traceview_picture_5.png

这个文件有下面几个重要信息

1. VERSION ~ Trace (1~29行)是线程信息,前面是线程 id 后面是 线程名称。

2. Trace 以后是方法信息。

第一部分是线程 id

第二部分 ent 代码方法开始执行,xit 表示方法执行完毕

第三部分表示当时的时间戳,单位是微秒(μs)

第四部分表示方法名,参数类名

提取需要的信息

在 gradle 再增加一个 task

task AppFilterMethodOrder() {

doLast {

//TODO 替换为你想要过滤的包名

def filterPackageName = "com.xxx.xxx"

if (project.hasProperty("package_name")) {

filterPackageName = project.getProperty("package_name")

}

//处理包名

def filterSignature = filterPackageName.replaceAll("[.]", "/")

def capturesDirPath = project.getProjectDir().path + File.separator + "captures";

def capturesDir = new File(capturesDirPath);

capturesDir.traverse {

if (it.isFile() && it.name.endsWith(".txt") && !it.name.contains("--filter")) {

def orderName = it.name.replace(".txt", "--filter.txt")

def orderFile = new File(capturesDirPath, orderName)

orderFile.write("")

def map = new HashMap();

it.eachLine { line ->

if (line.contains(filterPackageName) || line.contains(filterSignature)) {

if (line.contains("ent")) {

line = line.replaceAll("[.]{2,}+", "")

line = line.replaceAll("[ ]{2,}+", " ")

def item = line.split(" ");

map.put(item[3], item[2])

} else if (line.contains("xit")) {

line = line.replaceAll("[.]{2,}+", "")

line = line.replaceAll("[ ]{2,}+", " ")

def item = line.split(" ");

// for (int i = 0; i < item.length; i++) {

// println "--" + i + ":" + item[i]

// }

println map.size()

// println map.containsKey(item[3])

if (map.containsKey(item[3])) {

println item[3] + " 耗时:" + (item[2].toInteger() - map.get(item[3]).toInteger())/1000 + " 毫秒"

orderFile.append("耗时:\t\t" + (item[2].toInteger() - map.get(item[3]).toInteger())/1000 + " 毫秒" + "\t\t" + item[3])

orderFile.append("\n")

map.remove(item[3])

}

}

}

}

}

}

}

}

执行代码

gradlew AppFilterMethodOrder -P package_name=com.xxx.xxx

这个 task 中,我们根据包名提取需要的信息得到

1e038ef2e586

traceview_picture_6.png

参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值