gradle构建项目速度优化及排查方式
文章目录
- 一、前言
- 二、Android项目优化
- 1、相关配置
- 2、构建速度分析
- 三、Gradle项目通用优化
- 1、分析构建耗时
- 2、使用配置进行优化
- 3、优化依赖解析
- a. 避免不必要和未使用的依赖项
- b. 优化存储库顺序
- c. 最小化动态和快照版本
- d. 通过构建扫描查找动态和变化的版本
- e. 通过构建扫描可视化依赖关系解析
- f. 删除或改进自定义依赖解析逻辑
- g. 删除缓慢或意外的依赖项下载
- 4、远程缓存
- 四、参考链接
一、前言
gradle构建优化分为两部分,分别为Android上面的优化和gradle项目通用优化,使项目编译速度提升,节省开发时间。在此前提保持良好的编码习惯并减少代码和资源,也有利于提高编译速度。其中对于Android小型项目,Android官方提供的优化建议就足够了,过度优化有时候不见得能够提高构建速度。
二、Android项目优化
1、相关配置
这里根据官方文档整理后,将可以快速使用的配置记录如下:
app/build.gradle
android {defaultConfig {resourceConfigurations.addAll(["en", "xxhdpi"]) //限制资源版本}
}
gradle.properties
#在gradle高版本不再自动生成BuildConfig类,需要使用这个开启
android.defaults.buildfeatures.buildconfig=true
#使用非常量 R 类加速构建
android.nonFinalResIds=true
# 使用非传递 R 类方式加速构建
android.nonTransitiveRClass=true
android.useAndroidX=true
#如果项目都是androidX,可以把这个改为false,可以提高编译速度,但是编译会出警告,所以就不去掉了
android.enableJetifier=true
kotlin.code.style=official#-XX\:+UseParallelGC 使构建方式采用G1垃圾回收器。该配置对提高构建速度有明显效果
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding\=UTF-8 -XX\:+UseParallelGC#该配置可以启用缓存,对于第二次构建时候速度,效果明显,但是该功能属于测试功能,不支持所有插件,具体支持版本查看
#https://github.com/gradle/gradle/issues/13490
#不过对于Android官方插件一般都是支持的。
org.gradle.unsafe.configuration-cache=true
# Use this flag carefully, in case some of the plugins are not fully compatible.
org.gradle.unsafe.configuration-cache-problems=warn
对于除了gradle配置外,还有如图片采用webp格式,依赖库版本使用最新版本且是准确的版本号,避免使用'com.android.tools.build:gradle:2.+'
需要匹配的版本号。将相关代码转换为库文件等等方式。
如果项目中使用了gradlePluginPortal()
解析依赖需要将该依赖放在其余仓库后面。
因为Gradle 会按照声明的顺序搜索代码库,因此,如果先列出的代码库包含大多数插件,build 性能就会得到提升。因此,您可以尝试将
gradlePluginPortal() 条目放置在 settings.gradle
文件的代码库中最靠后的位置。在大多数情况下,这样可以最大限度地减少冗余插件搜索次数,并提高构建速度。
2、构建速度分析
这一个比较简单,基本上都源自官网
如需开始使用,请按以下步骤操作:
如果您尚未构建应用,请采用以下其中一种方法构建应用: 从菜单栏中依次点击 Build > Make Project。 如需构建
Android App Bundle 或 APK,请从菜单栏中依次点击 Build > Build Bundle(s) / APK(s) >
Build Bundle(s) 或 Build > Build Bundle(s) / APK(s) > Build APK(s)。
如需打开 Build 窗口,请从菜单栏中依次选择 View > Tool Windows > Build。 如需在 Build
Analyzer 中查看构建报告,请点击 Build 窗口中的 Build Analyzer 标签页。
编译完后如下
如需查看决定着构建时长的任务所属的插件的细分数据,请点击概览页面上的 Plugins with tasks impacting build
duration。您也可以从下拉菜单中选择 Tasks 并确认已选中 Group by plugin。 Build Analyzer
显示对构建时长影响最大的插件的详情。 任务窗格会显示为构建时长做出贡献的任务。任何有问题的任务旁边都会显示一个警告图标。该图表显示了任务在总构建时长中所占的百分比。
详细信息窗格会详细描述针对所选任务已检测到的问题。
每个节点都会显示执行其直属子节点所用的总时长。时长有助于您重点检查对构建时长影响最大的任务。
点击Tasks impacting build duration后会发现整体构建时长
左侧的条目可以任意选择,如果有需要优化的地方会出现警告,如果没有则不会出现警告,如下是一个警告的内容
这个含义说的很明白了,这里就不再多说了,解决方式可以通过点击下面蓝色文字Click here to migrate your project to use non-transitive R classes进行解决,或者手动解决,在gradle.properties
中添加如下内容
android.nonTransitiveRClass=true
修改完重新编译警告即可修复。不过有些无法解决,比如firebase
的插件
类似于这种优化只能是做能力范围之内的优化,并非所有优化都能做到极致。
对于Build Analyzer工具的使用较为简单,多点一下不到一分钟即可学会所有功能,这里不再详细赘述。
处理完后第二次构建的速度大约是一秒
BUILD SUCCESSFUL in 951ms
110 actionable tasks: 2 executed, 108 up-to-date
Configuration cache entry reused.
这么快主要还是因为开启了缓存功能
三、Gradle项目通用优化
1、分析构建耗时
在项目下面执行命令
./gradlew build --scan
会对项目进行构建扫描,将各个地方的构建时间显示出来,详细程度远非Android官方提供的方式可比。构建完会显示一个链接,打开后输入邮箱会将构建结果发送到邮箱中,但是该方式会导致gradle的销售以及gradle广告也推送过来。打开后页面效果如下:
如果不想写邮箱可以使用简略版本
./gradlew --profile build
编译完成后,会在本地生成一个xml文档,地址会显示在最后一行。默认会在 build/reports/profile根项目的目录中生成 HTML 报告。页面如下
这两种方式使用都比较简单,不在赘述,因为大部分项目也不自己编写task,所以耗时基本上都是因为在执行系统函数,也无从优化,如果是复杂项目可以查看执行的哪个task,然后进行优化。例如
本项目的整体构建时间图例
整体耗时task为:app:mergeExtDexDebug
。
2、使用配置进行优化
通过添加以下代码可以快速提高项目编译速度
gradle.properties
#gradle独有构建优化
#开启并行构建
org.gradle.parallel=true
#启用守护进程,gradle3.4版本后默认开启
org.gradle.daemon=true
#启用配置缓存
org.gradle.configuration-cache=true
#启用构建缓存
org.gradle.caching=true
build.gradle
//将编译器作为单独的进程运行,该配置效果卓越,该配置的目的是将java类的编译放在独立进程进行操作,java类越多效果越明显
tasks.withType(JavaCompile).configureEach {options.fork = true
}
3、优化依赖解析
a. 避免不必要和未使用的依赖项
管理第三方库及其传递依赖项会显着增加项目维护成本和构建时间。
注意未使用的依赖项:当第三方库停止使用时,不会从依赖项列表中删除。这种情况在重构过程中经常发生。您可以使用Gradle Lint 插件 来识别未使用的依赖项。
如果您只使用第三方库中的少量方法或类,请考虑:
在您的项目中自己实现所需的代码
如果它是开源的,则从库中复制所需的代码(带有归属!)
b. 优化存储库顺序
当 Gradle 解析依赖项时,它会按声明的顺序搜索每个存储库。为了减少搜索依赖项所花费的时间,请首先声明托管最大数量依赖项的存储库。这最大限度地减少了解决所有依赖关系所需的网络请求数量。
c. 最小化动态和快照版本
动态版本(例如“2.+”)和更改版本(快照)迫使 Gradle 联系远程存储库以查找新版本。默认情况下,Gradle 仅每 24 小时检查一次。但您可以通过以下设置以编程方式更改此设置:
cacheDynamicVersionsFor
cacheChangingModulesFor
如果构建文件或初始化脚本降低了这些值,Gradle 会更频繁地查询存储库。如果您不需要每次构建时都使用依赖项的绝对最新版本,请考虑删除这些设置的自定义值。
d. 通过构建扫描查找动态和变化的版本
您可以通过构建扫描找到具有动态版本的所有依赖项:
./gradlew build --scan
将'com.android.tools.build:gradle:2.+'
类似的动态版本替换为准确版本'com.android.tools.build:gradle:2.3'
e. 通过构建扫描可视化依赖关系解析
构建扫描提供了另一种识别此问题的方法。您的构建应该在“项目配置”期间花费 0 秒来解决依赖关系。此示例显示构建在生命周期中过早地解决了依赖关系。您还可以在“性能”页面上找到“设置和建议”选项卡。这显示了在配置阶段解决的依赖关系。
f. 删除或改进自定义依赖解析逻辑
Gradle 允许用户以最适合他们的方式对依赖解析进行建模。简单的自定义(例如强制依赖项的特定版本或将一种依赖项替换为另一种依赖项)不会对依赖项解析时间产生太大影响。更复杂的自定义(例如下载和解析 POM 的自定义逻辑)可能会显着减慢依赖关系解析速度。
使用构建扫描或配置文件报告来检查自定义依赖项解析逻辑是否不会对依赖项解析时间产生不利影响。这可能是您自己编写的自定义逻辑,也可能是插件的一部分。
g. 删除缓慢或意外的依赖项下载
缓慢的依赖项下载可能会影响您的整体构建性能。有多种原因可能会导致这种情况,包括互联网连接速度慢或存储库服务器过载。在构建扫描的“性能”页面上,您将找到“网络活动”选项卡。此选项卡列出的信息包括:
下载依赖项所花费的时间
依赖下载的传输速率
按下载时间排序的下载列表
在以下示例中,两次缓慢的依赖项下载分别花费了 20 秒和 40 秒,并降低了构建的整体性能:
4、远程缓存
通过远程缓存可以将多人共同的项目缓存进行共用,这在协作开发中与本地缓存结合起来能大幅度节约开发时间,该远程缓存可以自己搭建缓存服务器,也可以使用gradle提供的收费的或者免费的缓存服务。关于远程缓存内容较为复杂,会在后续重新整理,暂时可查看以下链接
Build Cache
Build Cache Node User Manual。
四、参考链接
- 优化构建速度
- 使用 Build Analyzer 排查构建性能问题
- Inspecting Gradle Builds
- Build Cache
- Build Cache Node User Manual
相关文章:

gradle构建项目速度优化及排查方式
文章目录 一、前言二、Android项目优化1、相关配置2、构建速度分析 三、Gradle项目通用优化1、分析构建耗时2、使用配置进行优化3、优化依赖解析a. 避免不必要和未使用的依赖项b. 优化存储库顺序 c. 最小化动态和快照版本d. 通过构建扫描查找动态和变化的版本e. 通过构建扫描可…...

MSI Center,XBox从任务栏取消固定
1,设置查看方式中隐藏项目可见 2,进入文件夹:C:\Users\Default\AppData\Local\Microsoft\Windows\Shell 找到下面这两个文件夹: 3,修改文件名或者删除这两个文件即可...

1、postman的安装及使用
一、安装、登录 1.安装 下载地址 2.注册登录(保存云服务进度) 二、界面介绍 三、执行接口测试页面 请求页签: 1、params:当是get请求时,通过params传参 2、authorization:鉴权 3、headers࿱…...

VUE简易计划清单
目录 效果预览图 完整代码 效果预览图 完整代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>…...
c++日志单例实现
为了使项目的所有日志都打印到同一个日志中,必须使得所有类使用同一个日志,因此将日志类实现为单例。 .h文件 #pragma once#include<fstream>class LogHablee { private:LogHablee(std::string& dbg_dir);LogHablee(const LogHablee&) …...
C/C++实现:找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和 某知名企业笔试题
目录 题目描述: 示例 1: 示例 2: 示例 3: 提示: 思路:...
Qt实现绘制自定义形状
先创建一个继承自QWidget的控件: class MyPainterWidget:public QWidget 重写各种鼠标方法: protected:void paintEvent(QPaintEvent *) override;void mousePressEvent(QMouseEvent *e) override; //按下void mouseMoveEvent(QMouseEvent *e) …...

WordPress安装AWS插件实现文本转语音功能
适用于 WordPress 的 AWS 插件示例演示了内容创建者如何轻松地为所有书面内容添加文本转语音功能。随着语音搜索的不断增加,以音频格式提供更多网站内容变得至关重要。通过添加语音功能,网站访客可以通过在线音频播放器和播客应用程序等新渠道使用您的内…...
87-96-多维动态规划、技巧
LeetCode 热题 100 文章目录 LeetCode 热题 100多维动态规划87. 中等-不同路径88. 中等-最小路径和89. 中等-最长回文子串90. 中等-最长公共子序列91. 困难-编辑距离 技巧92. 简单-只出现一次的数字93. 简单-多数元素94. 中等-颜色分类95. 中等-下一个排列96. 中等-寻找重复数 …...

NX二次开发UF_CURVE_ask_wrap_curve_parents 函数介绍
文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_wrap_curve_parents Defined in: uf_curve.h int UF_CURVE_ask_wrap_curve_parents(tag_t curve_tag, tag_t * defining_face, tag_t * defining_plane, tag_t * defin…...

使用 HTML、CSS 和 JavaScript 创建图像滑块
使用 HTML、CSS 和 JavaScript 创建轮播图 在本文中,我们将讨论如何使用 HTML、CSS 和 JavaScript 构建轮播图。我们将演示两种不同的创建滑块的方法,一种是基于opacity的滑块,另一种是基于transform的。 创建 HTML 我们首先从 HTML 代码开…...

ubuntu环境删除qtcreator方法
文章目录 方法1方法2方法3参考不同的安装方法,对应不同的删除方法 方法1 apt-get或者dpkg 方法2 QtCreatorUninstaller 方法3 MaintenanceTool...
软件测试基础知识
软件测试基本概念 1、软件程序文档,软件测试程序测试文档测试。 “程序”是指能够实现某种功能的指令的集合,“文档”是指软件在开发、使用和维护过程中产生的图文集合。; 2、软件的分类 按功能分:系统软件、应用软件 按技术架构分…...
使用 .toISOString() 方法生成当前时间的ISO格式字符串,解决UTC时区差问题
方法分析: 日常开发中,有时我们需要向后端传递的时间值可能并非一个时间对象,而是字符串格式。 例 1:[2023-08-16T08:07:25.577Z] 但是我们通过 new Date() 之后直接使用 .toString() 方法得到的却并非这种格式。 例 2࿱…...

“BMP转PNG一键转换,批量处理图片,迈入高效图片管理新时代“
你是否曾经为了转换图片格式而烦恼?是否曾经因为一张一张地手动转换而感到无奈?现在,我们的全新工具将为你解决这些问题,开启高效图片管理新时代! 首先,我们进入首助编辑高手主页面,会看到有多种…...

解决Vue编程式导航路由跳转不显示目标路径问题
我们配置一个编程式导航的路由跳转,跳转到 /search 页面,并且携带categoryName和categoryId两个query参数。 this.$router.push({path: "/search",query: {categoryName: dataset.categoryname,categoryId: dataset.categoryid} }) 如果我们…...
Android studio 引用framework.jar
framework.jar 引用目录 N/O: out/target/common/obj/JAVA_LIBRARY/framework_interminate/classes.jarAndroid 9/10: out/soong/.intermediates/frameworks/base/framework/android_common/combined/framework.jarAndroid 11: out/soong/.intermediates/framewo…...

软著项目推荐 深度学习 python opencv 火焰检测识别 火灾检测
文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数:3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…...

宝塔面板安装搭建DiscuzQ论坛教程与小程序上架发布后的展示效果
DiscuzQ论坛小程序上架发布后的展示效果: 1、需要用到的环境: php7.2 mysql5.7或者MariaDB 10.2(我安装用的mysql8.0) php除了必要的一些扩展外,还需要启用readlink、symlink函数等,具体看官方说明,安装的时候也会提醒…...

交换机配置与管理
文档以国产迈普交换机为例,各厂家交换机配置有少许不同,仅供参考。 交换机命令行模式: 普通用户模式Hostname>() exit 输入enable命令 特权用户模式Hostname#() exit 输入configu…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...