引言
本文重点
以上为本文全部主要内容,下面的啰嗦都是对以上内容的具体阐释。
获得 trace 文件
通过点击 DDMS start Method Profiling (第一次点击开始,第二次点击结束)
traceview_picture_1.png traceview_picture_2.png在代码中通过使用
android.os.Debug.startMethodTracing()
android.os.Debug.stopMethodTracing()
生成 traceView ,然后通过下面的 adb pull 命令导出 traceView
在 AndroidStudio 中获取,这个是本文重点,上面两种方式纯属为了凑数
点击 monitors cpu 模块的小闹钟(第一次点击开始,第二次点击结束)
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 文件
traceview_picture_4.pngtxt 文件比较大,AndroidStudio 自带的文本阅读器打不开,需要用其他工具打开(这里使用的是 sublime Text)下面是截取的一部分 txt 内容
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 中,我们根据包名提取需要的信息得到
traceview_picture_6.png