This post is a quick write-up of an experiment where I use remote execution to build my Bazel project.

For remote execution I am using the bazel build farm project.

The build farm sample project pretty much works out of the box, but I’ve made a few dependency tweaks to support specific dependencies in my target project. My own personal fork of build farm be found here.

Build Farm

To launch build farm we have to launch a server process and a worker process. Both can be started by running server.sh and worker.sh in separate terminal windows.

In my implementation I follow the original example from the build farm documentation, but I have increased the max number of concurrent executions to 10. I am also running the worker process on two different computers, which means my setup supports up to 20 concurrent executions.

The number of concurrent executions is controlled through the worker process by setting execute_stage_width=n in the worker config file (see build farm config).

Unlike the worker process, the server process is only running on one of the boxes.

Building

Once build farm is running, only minor changes in bazel.rc are required to enable remote execution.

Here is the config I am running with:

build --spawn_strategy=remote --genrule_strategy=remote --strategy=TypeScriptCompile=remote --strategy=Javac=remote --strategy=Closure=remote --remote_executor=my-server:8980

This setting tells Bazel to invoke remote executors when building.

My project is a full stack project consisting of Angular, Express and Java.

So far I am able to use remote executors to build Express (Typescript) and Java, but Angular (AOT compilation) is not working yet.

Regular Typescript builds work fine, but Angular AOT is failing since it uses an extension of the regular Typescript compiler. I haven’t figured out how to add the Angular compiler dependencies in the remote build yet.

Since Angular AOT compilation fails in the remote build, I have opted out of remote execution for the Angular bits by adding the following to bazel.rc:

build –strategy=AngularTemplateCompile=worker

Remote vs Local

Remote builds allow us to spread execution load across multiple computers. This will likely decrease build times since more of the build can be processed in parallel on powerful servers.

That said, it’s important to ensure a fast connection between build nodes. Otherwise, network latency may negate the benefit of remote execution.

Still, even if your build times aren’t guaranteed to be faster, you will have the benefit of a remote cache on rebuilds. Since the remote build creates a centralized cache, subsequent builds can read from the cache, even after doing a bazel clean locally.

Results

Time to compare build times…

Sadly, I don’t have access to a large server farm, but as I mentioned earlier, I did set up a “network” of two decent computers.

The baseline build time from running a local build was 86 seconds. When running with remote executors I reduced the build time to 65 seconds. This is a reduction of about 24% which is pretty promising.

For this initial experiment I only compared the Java portion of the application.

My hope is that remote execution will be even more impactful on the Angular portion of the application. The Angular portion consists of many more modules, so a parallel build should scale well.