搜索
您的当前位置:首页正文

TraceView 的正确打开方式

来源:二三娱乐

引言

本文重点

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


获得 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.png

txt 文件比较大,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

参考资料

Top