分享一个统计 Android 模块构建时长的脚本工具

2 篇文章 0 订阅
2 篇文章 0 订阅

背景

通常我们会遇到项目中存在很多模块的情况,每次构建都会花费好久,但是又不知道每个模块耗费多久,因此使用该工具可以很方便的检测,用来决定如何优化项目结构

实现效果

构建总耗时:6637ms 
app, 总耗时:4943ms 
xxx-util, 总耗时:90ms 
lib, 总耗时:148ms 
xxx_browser, 总耗时:22ms 
videoxxx, 总耗时:33ms 
xxxmodule, 总耗时:90ms 
xxx_message, 总耗时:69ms 
xxx_notchtoolslib, 总耗时:46ms 
xxx_zxing, 总耗时:27ms 
xxx_emojilib, 总耗时:36ms 
xxx_magicindicator, 总耗时:20ms 
xxx_uselogin, 总耗时:46ms 
xxxPlugin, 总耗时:92ms 
xxxcommonlib, 总耗时:53ms 
xxxmvvm, 总耗时:55ms 

这样很容易就能看到每个模块耗时多久。

使用源码方式

  1. 在 app/build.gradle 添加
...
apply from: "../buildTrace.gradle"
...

  1. 项目根目录下

buildTrace.gradle

import java.text.SimpleDateFormat

/**
 * 监控构建耗时
 *
 * 记录构建过程中的每个任务的耗时,并写入文件中 .build_history/buildTimeLog_yy_MM_dd_HH_mm_ss.log中
 */

class BuildTimeListener implements TaskExecutionListener, BuildListener {
    private final String BUILD_LOG_FILE_DIR = ".build_history"
    private final String BUILD_LOG_FILE_PATH = "buildTimeLog"
    private long taskStartTime;
    private long buildStartTime;
    private int taskCounts = 0;
    private StringBuilder sb = new StringBuilder()
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    private SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss")
    private SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS")

    private Map<String, Long> moduleTimeMap = new HashMap<>()

    BuildTimeListener() {
        buildStartTime = System.currentTimeMillis()
        sb.append("构建时间:" + sdf3.format(new Date()) + "\n")
        sb.append("开始构建----------------------\n")
    }

    @Override
    void buildStarted(Gradle gradle) {

    }

    @Override
    void settingsEvaluated(Settings settings) {

    }

    @Override
    void projectsLoaded(Gradle gradle) {

    }

    @Override
    void projectsEvaluated(Gradle gradle) {

    }

    /**
     * 构建完成回调
     * @param result The result of the build. Never null.
     */
    @Override
    void buildFinished(BuildResult result) {
        if(taskCounts<5) return
        long buildCost = System.currentTimeMillis() - buildStartTime
        sb.append("构建结束------------------" + sdf3.format(new Date()) + "----\n")
        sb.append("构建总耗时:" + buildCost + "ms \n")

        for (Map.Entry<String, Long> entry : moduleTimeMap.entrySet()) {
            sb.append(entry.key + ", 总耗时:" + entry.value + "ms \n")
        }


        //输出到文件
        String text = sb.toString()
        writeToFile(BUILD_LOG_FILE_PATH, text)
    }

    /**
     * 任务执行开始
     * @param task The task about to be executed. Never null.
     */
    @Override
    void beforeExecute(Task task) {
        taskStartTime = System.currentTimeMillis();
        task.name

        String moduleName = task.path.split(":")[1]
        String taskName=task.name

//        moduleTimeMap.put(moduleName, 0)
    }

    /**
     * 任务执行结束
     * @param task The task which was executed. Never null.
     * @param state The task state. If the task failed with an exception, the exception is available in this
     */
    @Override
    void afterExecute(Task task, TaskState state) {
        long cost = System.currentTimeMillis() - taskStartTime;
        System.out.println("任务:" + task.name + "," + task.path + ",耗时:" + cost + " \n")

        String timeStamp = sdf3.format(new Date())
        String moduleName = task.path.split(":")[1]
        String taskName=task.name

        Long preTotalTime = moduleTimeMap.get(moduleName)
        if (preTotalTime != null) {
            preTotalTime+=cost
            moduleTimeMap.put(moduleName, preTotalTime)
        } else {
            moduleTimeMap.put(moduleName, cost)
        }

        sb.append(timeStamp + ": 【" + moduleName + "】" + taskName + "=" + cost +  "ms \n")
        taskCounts++
    }

    private void writeToFile(String fname, String text) {
        File dir = new File(BUILD_LOG_FILE_DIR)
        if (!dir.exists()) {
            dir.mkdir()
        }

        File file = new File(BUILD_LOG_FILE_DIR + File.separator + fname + "_" + sdf2.format(new Date()) + ".log")
        file.write(text)
    }
}

gradle.addListener new BuildTimeListener()

如果查看?

当运行 app 项目,会自动在项目的根目录下创建 .build_history 文件夹,并且根据时间戳把耗时日志保存到本地,开始是每个模块的单独任务,最后进行汇总,模块的使用时间。查看对应文件即可。

.
├── app
├── build.gradle
├── buildTrace.gradle
├── .build_history
│   ├── buildTimeLog_2022_02_15_18_34_26.log
│   └── buildTimeLog_2022_02_15_18_35_50.log
├── gradle
└── testlib

给一个完整文件示例:
buildTimeLog_2022_02_15_18_35_50.log

构建时间:2022-02-15 18:35:42:193
开始构建----------------------
2022-02-15 18:35:42:280: 【app】preBuild=0ms 
2022-02-15 18:35:42:281: 【app】preDebugBuild=0ms 
2022-02-15 18:35:42:281: 【testlib】preBuild=0ms 
2022-02-15 18:35:42:282: 【testlib】preDebugBuild=0ms 
2022-02-15 18:35:42:285: 【testlib】compileDebugAidl=2ms 
2022-02-15 18:35:42:287: 【app】compileDebugAidl=1ms 
2022-02-15 18:35:42:288: 【testlib】packageDebugRenderscript=0ms 
2022-02-15 18:35:42:290: 【app】compileDebugRenderscript=1ms 
2022-02-15 18:35:42:409: 【app】dataBindingMergeDependencyArtifactsDebug=118ms 
2022-02-15 18:35:42:418: 【app】dataBindingMergeGenClassesDebug=9ms 
2022-02-15 18:35:42:419: 【app】generateDebugResValues=0ms 
2022-02-15 18:35:42:420: 【app】generateDebugResources=0ms 
2022-02-15 18:35:42:422: 【testlib】compileDebugRenderscript=0ms 
2022-02-15 18:35:42:423: 【testlib】generateDebugResValues=1ms 
2022-02-15 18:35:42:423: 【testlib】generateDebugResources=0ms 
2022-02-15 18:35:42:426: 【testlib】packageDebugResources=2ms 
2022-02-15 18:35:43:409: 【app】generateDebugBuildConfig=3ms 
2022-02-15 18:35:43:422: 【app】javaPreCompileDebug=1ms 
2022-02-15 18:35:43:423: 【testlib】writeDebugAarMetadata=0ms 
2022-02-15 18:35:43:443: 【app】createDebugCompatibleScreenManifests=1ms 
2022-02-15 18:35:43:444: 【app】extractDeepLinksDebug=1ms 
2022-02-15 18:35:43:445: 【testlib】extractDeepLinksDebug=1ms 
2022-02-15 18:35:43:449: 【testlib】processDebugManifest=2ms 
2022-02-15 18:35:43:622: 【app】processDebugMainManifest=172ms 
2022-02-15 18:35:43:627: 【app】processDebugManifest=4ms 
2022-02-15 18:35:43:631: 【app】checkDebugAarMetadata=3ms 
2022-02-15 18:35:43:634: 【testlib】compileDebugLibraryResources=1ms 
2022-02-15 18:35:43:639: 【testlib】parseDebugLocalResources=5ms 
2022-02-15 18:35:43:648: 【testlib】generateDebugBuildConfig=1ms 
2022-02-15 18:35:43:650: 【testlib】javaPreCompileDebug=0ms 
2022-02-15 18:35:43:651: 【app】mergeDebugNativeDebugMetadata=1ms 
2022-02-15 18:35:43:653: 【app】mergeDebugShaders=1ms 
2022-02-15 18:35:43:655: 【app】compileDebugShaders=1ms 
2022-02-15 18:35:43:656: 【app】generateDebugAssets=0ms 
2022-02-15 18:35:43:658: 【testlib】mergeDebugShaders=2ms 
2022-02-15 18:35:43:660: 【testlib】compileDebugShaders=1ms 
2022-02-15 18:35:43:660: 【testlib】generateDebugAssets=0ms 
2022-02-15 18:35:43:662: 【testlib】packageDebugAssets=1ms 
2022-02-15 18:35:43:683: 【app】mergeDebugAssets=20ms 
2022-02-15 18:35:43:685: 【app】compressDebugAssets=1ms 
2022-02-15 18:35:43:687: 【app】processDebugJavaRes=1ms 
2022-02-15 18:35:43:688: 【testlib】processDebugJavaRes=0ms 
2022-02-15 18:35:43:690: 【testlib】bundleLibResDebug=1ms 
2022-02-15 18:35:43:727: 【testlib】generateDebugRFile=36ms 
2022-02-15 18:35:44:855: 【testlib】compileDebugJavaWithJavac=1126ms 
2022-02-15 18:35:44:876: 【app】mergeDebugJavaResource=20ms 
2022-02-15 18:35:44:899: 【app】desugarDebugFileDependencies=1ms 
2022-02-15 18:35:44:939: 【app】mergeDebugResources=39ms 
2022-02-15 18:35:44:941: 【app】dataBindingGenBaseClassesDebug=1ms 
2022-02-15 18:35:44:943: 【app】mergeDebugJniLibFolders=1ms 
2022-02-15 18:35:44:944: 【testlib】mergeDebugJniLibFolders=0ms 
2022-02-15 18:35:44:946: 【testlib】mergeDebugNativeLibs=1ms 
2022-02-15 18:35:44:947: 【testlib】stripDebugDebugSymbols=1ms 
2022-02-15 18:35:44:948: 【testlib】copyDebugJniLibsProjectOnly=1ms 
2022-02-15 18:35:44:964: 【app】validateSigningDebug=0ms 
2022-02-15 18:35:44:965: 【app】writeDebugAppMetadata=1ms 
2022-02-15 18:35:44:966: 【app】writeDebugSigningConfigVersions=1ms 
2022-02-15 18:35:44:967: 【testlib】bundleLibRuntimeToDirDebug=2ms 
2022-02-15 18:35:44:968: 【testlib】bundleLibCompileToJarDebug=3ms 
2022-02-15 18:35:44:970: 【app】checkDebugDuplicateClasses=5ms 
2022-02-15 18:35:45:002: 【app】processDebugManifestForPackage=28ms 
2022-02-15 18:35:45:316: 【app】mergeLibDexDebug=18ms 
2022-02-15 18:35:46:448: 【app】mergeDebugNativeLibs=1149ms 
2022-02-15 18:35:46:456: 【app】stripDebugDebugSymbols=7ms 
2022-02-15 18:35:48:751: 【app】processDebugResources=2303ms 
2022-02-15 18:35:49:288: 【app】compileDebugJavaWithJavac=533ms 
2022-02-15 18:35:49:288: 【app】compileDebugSources=0ms 
2022-02-15 18:35:49:772: 【app】dexBuilderDebug=481ms 
2022-02-15 18:35:49:835: 【app】mergeExtDexDebug=62ms 
2022-02-15 18:35:50:035: 【app】mergeProjectDexDebug=262ms 
2022-02-15 18:35:50:420: 【app】packageDebug=384ms 
2022-02-15 18:35:50:421: 【app】assembleDebug=0ms 
构建结束------------------2022-02-15 18:35:50:441----
构建总耗时:8248ms 
app, 总耗时:5635ms 
testlib, 总耗时:1190ms 

这样就能看出来是 testlib 占用 1.1s, 把占比最高的,抽离成 aar 即刻实现项目编译的更快。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值