Reducing VS Code CI build times by 33%

Ethan Dennis
Crawl, walk, sprint
3 min readFeb 28, 2019

(Hey! We’ve moved the home of Crawl Walk Sprint. This post can be found at its new home here.)

A problem that software projects can run into while optimizing their continuous integration (CI) builds is the long time spent resolving external dependencies. For example, VS Code CI builds take roughly 6 minutes to resolve node packages for a Windows build. A common solution among CI providers is to enable caching of the resolved dependencies as an explicit build step. Until now, Azure DevOps did not have a easy solution for this — but this is about to change. I am extremely happy to announce the release of Azure Pipelines Artifact Caching Tasks, which allows you to restore and save build caches in Azure Artifacts with a couple of drop-in build tasks!

VS Code CI build times showing drop off after onboarding the build task.

How it works

Let’s examine the following build definition snippet:

Conceptually, this snippet creates a lookup key from the keyfile argument and checks the vstsFeed for a matching entry. If one exists, it will be downloaded and unpacked. After more node_modules are restored via yarn the SaveCache task runs to create a cache entry if it wasn’t available previously (if a cache entry was downloaded, this is a no-op).

Inputs:

  • keyfile: The file or pattern of files to use for creating the lookup key of the cache. Due to the nature of node_modules potentially having their own yarn.lock file, this snippet explicitly excludes that pattern to ensure there is a consistent lookup key before and after package restoration.
  • targetfolder: The file/folder or pattern of files/folders that you want to cache. The matching files/folders will be represented as the universal package that is uploaded to your Azure DevOps artifact feed.
  • vstsFeed: The guid representing the artifact feed in Azure DevOps meant to store the build’s caches.

If you do not want to add two build steps to your build definition, you can optionally use a single task that implicitly adds the SaveCache task at the end of the build. For example:

Optimistic cache restoration

If a cache was restored successfully, the build variable CacheRestored is set to true. This can provide a further performance boost by optionally skipping package install commands entirely.

In the following example, the yarn task will only run if there was not a cache hit. Although this can provide faster builds, it may not be suitable for production builds.

What are the benefits

To demonstrate how much this can speed up your builds, we can compare the VS Code build pipelines using artifact caching and without using artifact caching.

With these changes, the total build time reduced from 19 minutes to 12 minutes; representing a 36% decrease in build time!

The build results using the cache can be found here, and the build results without using the cache can be found here.

What’s next

Go ahead and start using this task in your builds! If you have any issues, feel free to file issues (or enhancements) here.

Also, in case you missed it, this feature is coming more natively to Azure Pipelines! Go ahead and comment on the design proposal.

--

--