为什么Gradle缓存多次包含依赖项?

3yhwsihp  于 2023-05-29  发布在  其他
关注(0)|答案(1)|浏览(224)

bounty还有2天到期。此问题的答案有资格获得+50声望奖励。roookeee希望引起更多关注这个问题。

我们正在通过Gitlab Pipeline Jobs将Gradle缓存作为ZIP上传到S3。解压缩其中一个ZIP文件(仅包含.gradle文件夹)显示,许多依赖项被包含多次使用完全相同的版本jars-9中的1x和modules-2中的1x:

为什么会发生这种情况,如何避免?因此,我们的CI缓存比需要的大20-30%,特别是对于像Kotlin编译器这样的大依赖:

JAR之间的大小差异可以归因于JAR文件压缩的打开或关闭,它们在内容方面是相同的。
关于.gradle文件夹结构的official explanation没有帮助。

aydmsdu9

aydmsdu91#

Gradle的依赖缓存旨在提高效率和可靠性。它包括两种主存储类型:
1.基于文件的已下载工件存储,包括jar等二进制文件和POM和Ivy文件等原始已下载元数据。下载的工件的存储路径包括SHA1校验和,这意味着可以轻松缓存两个名称相同但内容不同的工件($GRADLE_USER_HOME/caches)。
1.已解析模块元数据的二进制存储,包括解析动态版本、模块描述符和工件的结果。
您在Gradle缓存中看到的jars-*modules-2目录属于这两种不同类型的存储。
jars-*目录可能是指下载工件的基于文件的存储。存储在此目录中的每个工件都在其存储路径中包含SHA1校验和。这种设计允许Gradle缓存两个具有相同名称但不同内容的工件,并且还确保如果同一工件已经存在该高速缓存中并具有相同的SHA1校验和,则不会多次下载该工件。
另一方面,modules-2目录可能是指已解析模块元数据的二进制存储。该目录以二进制格式保存依赖关系解析的各个方面的记录,包括将动态版本解析为具体版本的结果、特定模块的解析模块元数据以及特定工件的解析工件元数据。
这两个目录是不同的,因为它们用于不同的目的并存储不同类型的数据。两个目录中存在相同的依赖项并不一定意味着数据是重复的。相反,很可能一个目录包含实际的工件(例如jar文件),而另一个目录包含关于工件的元数据。
Gradle还应用各种清理策略来防止该高速缓存无限增长。默认情况下,它会检查缓存是否仍在使用,并删除未使用的缓存。共享缓存中在一段时间内未被访问的文件也会被删除。
在减少CI缓存的大小方面,考虑到Gradle缓存的工作方式,不同缓存目录中相同依赖项的多个示例可能无法避免。但是,您可以将CI/CD管道配置为仅缓存必要的目录或文件,或者使用增量构建等技术来最大限度地减少需要缓存的数据量。您还可以考虑定期手动或以编程方式清理Gradle缓存,以删除未使用或过时的文件。

相关问题