Gradle与Bazel的构建性能比较

11

现在大家都在谈论Bazel,但是从Maven迁移到它并没有自动化(相较于Gradle而言,Gradle在这方面更好)。所以我不想花时间手动将任何存储库转换为它。

但我找不到任何关于最近版本的Gradle(5.6 >)和Bazel(1.0)之间构建速度差异的信息。

有人能分享链接或他自己的经验吗?我主要感兴趣的是增量构建,在这种情况下只有几个文件发生了变化。

2个回答

9

Dropbox 最近 进行了一些基准测试:

enter image description here

请注意,对于Bazel而言,没有缓存的清洁构建方案明显较慢,而增量构建方案则明显更快。
与Gradle相比,Bazel构建单元往往具有更小的粒度。通常可以看到只有一个源文件的java_library目标。这些构建单元中的命令行操作(也称为目标)会被单独缓存(本地或远程),并组合在一起构建一个java_binary
由于存在许多小型构建单元,通常需要执行更多动作,因此需要更多磁盘I/O和计算,导致初始的清洁构建时间变慢。
这些操作的某些可执行文件可能也具有很高的启动成本(例如javac),当这些进程多次重新启动时,这些成本就会累加。Bazel具有一种称为持久化工作者的机制,其中针对各个操作的可执行进程(例如javactscscalacghc的编译器包装程序)可以在操作执行期间保留,从而节省启动时间,并在进程级别上实现更低级别的缓存。
另一方面,Bazel的小型构建单元使高度增量构建和快速迭代开发成为可能,如上图所示。
小型构建单元还使得Bazel能够形成具有高度并行性的依赖关系图。通过远程执行,您可以并行运行数百个甚至数千个小型构建操作。
依赖关系图也高度优化了无操作构建情况。如果项目中没有任何更改,Bazel应该尽可能少地花费时间来确定没有更改,因此不需要执行任何操作。
缓解缓慢清理构建的缺点也可以通过远程缓存、远程执行或不经常运行相对较少的bazel clean来实现,因为构建旨在具有隔离性、确定性和一致性。使用100%远程缓存命中的构建在Bazel中很常见。

1
这个比较没有意义,因为最重要的部分是gradle与构建缓存相比,bazel与构建缓存和增量编译相比。至于构建的粒度 - 我不明白这有什么关系。Gradle支持将Java的增量编译降到文件级别。无论如何,您都需要找到整个项目中已更改的文件,对吧?您能详细说明一下吗?还不清楚他们使用的Gradle版本。因此,我严重怀疑这些比较是否做得正确... - user1685095
2
没有28.6秒的无操作构建?如果他们有这样的配置时间,那么他们可能没有正确使用Gradle。 - user1685095
我认为他们也没有正确地使用Gradle。构建时间太长了。 - cocorossello
1
构建单元越细粒度,构建系统就能更好地将工作并行化到执行线程中,并最小化需要完成的工作量。您可以比较具有100个Java源文件的java_library和10个每个包含10个源文件的java_library目标,这些目标连接在DAG中。对于后者,更改Java源文件通常不会每次触发100个源文件的重新编译。如果修改Java文件的非ABI部分,则差异更加明显。 - Jin
1
关于Gradle,我不清楚Dropbox如何构建他们的项目。你可以使用https://github.com/jin/android-projects进行基准测试比较 - 我个人的基准测试结果是可靠的。 - Jin
我尝试了一下你的Android项目,并在“java_only”模块中进行了更改以测试增量构建。在每种情况下,Gradle都比较快,无论是增量构建测试还是缓存构建(我已经执行了git restore)。我猜你的基准测试已经过时了,因为你使用的是Gradle 4.12,而在Gradle 5.0及更高版本中有很多改进。但仅从Gradle团队的基准测试来看,他们说可以在3秒内构建1000个模块的Java项目。所以我非常确定使用Bazel没有性能优势。 - user1685095

2

好的,我已经将包含约100,000行Java代码的闭源项目迁移到了Bazel。

Gradle 5.6.3 和 bazel 1.0.1

正如我所说,我的兴趣在于开发人员的生产力,因此也关注增量构建。

我在Bazel的BUILD中使用了以下内容,因此我没有使用最细粒度的方法,因为我认为这不是可维护的,并且除了拥有很多DevOps的大公司之外,任何人都无法使用。无论如何,我认为需要手动执行此操作以提高构建速度是Bazel的缺点之一。

java_binary(
    srcs = glob(["src/main/java/**/*.java"]),
    resources = glob(["src/main/resources/**"]),
    ...
)

一到两个文件的增量构建。

gradle - 1秒,bazel - 4.227秒

我尝试了多次,每次gradle都明显更快。我没有测试过当有一个或两个以上的文件被更改时的增量构建,也许在这种情况下bazel与gradle相同或更快。

无操作构建 gradle - 700毫秒,bazel - 0.090毫秒

因此,在开发者生产力方面,速度方面gradle似乎是赢家。Bazel具有更安全的默认设置(默认启用错误检测),而在gradle中,您必须自己启用它,但在我看来,gradle的灵活性超过了bazel的更多安全默认设置。


4
如果不将Bazel的构建细分,您基本上正在否定Bazel的最大优点。如果有更细的粒度,则增量构建时间应该会显著缩短。 - aljoscha
5
我知道并认为任何一个理智的现代构建系统都应该自动为我完成这个任务。我只需要说明我想编译Java项目,例如Shake、Meson和Redo。 - user1685095

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接