Gradle vs Bazel performance of builds

Dropbox ran some benchmarks recently:

enter image description here

Note that the clean build without a cache scenario is significantly slower for Bazel, whereas the incremental build scenario is significantly faster.

Bazel build units tend to have a smaller granularity than Gradle's. It's common to see java_library targets with just a single source file. The command line actions in these build units, also known as targets, are individually cached (locally or remotely) and composed together to build a java_binary.

With many small build units, there are typically more actions to execute, and therefore more disk I/O and computation, leading to a slower initial, clean build time.

Some executables of these actions may also have a high startup cost (e.g javac), which adds up when these processes are restarted many times. Bazel has a mechanism called persistent workers, where the executable process for individual actions (e.g. a compiler wrapper for javac, tsc, scalac or ghc) can be persisted across action executions, saving on startup times and enabling an even lower level of caching at the process level.

On the other hand, Bazel's small build units enable highly incremental builds and fast iterative development, as seen in the chart above.

The small build units also enable Bazel to form a dependency graph with a high degree of parallelism. With remote execution, you can run 100s and 1000s of small build actions in parallel.

The dependency graph is also highly optimized for the no-op build case. If nothing has changed in your project, Bazel should take as little time as possible to figure out nothing has changed, so nothing needs to be done.

The drawback of a slow clean build can also be mitigated with remote caches, remote execution, or not running the relatively rare bazel clean since builds aim to be hermetic, deterministic, and consistent. A build with 100% remote cache hits are common with Bazel.


Okay, I've migrated closed source project containing ~100_000 loc of java to bazel.

Gradle 5.6.3 vs bazel 1.0.1

As I've said my interest is about developer productivity and hence about incremental builds.

I've used the following in BUILD for bazel so I haven't used most granular approach because I don't think it's really maintainable and that anybody except big companies with a lot of devops could use that. And in any case I see the fact that I would need to do this manually to improve build speed as a downside of bazel.

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

Incremental build with one or two changed files.

gradle - 1s, bazel - 4.227s

I've tried that multiple times and each time gradle was significatly faster. I Haven't tested incremental build when more than one or two files have been changed, maybe in that scenario bazel would be the same or faster than gradle.

No op build gradle - 700ms, bazel - 0.090ms

So speed-wise gradle seems to be the winner for developer productivity. Bazel have more safe defaults (error-prone is on by default) in gradle you have to enable it yourself, but IMHO the flexibility of gradle outweighs more safe defaults of bazel.