Vagrant Shared Filesystem Comparison
At my current company, we use Vagrant to create and maintain virtual machines in a reproducible manner. Our developers use their host machine to write code, then use a Vagrant VM to compile our application.
Vagrant can use several technologies to keep a folder on the host machine synchronized with the guest virtual machine: NFS, RSync, SMB, or Virtualbox. Each of these technologies has difference performance characteristics, which results in dramatically different compilation times, ranging from 30 seconds to over 5 minutes.
The workload when compiling our application is composed of small file reads interspersed with small file writes, in the range of 0.5KB to 8KB, with a few outliers in the 10s of KB – nearly a worst-case workload for I/O. In this post, I will benchmark the synchronized folder options in Vagrant, and share our current best-practice for reducing compilation times.
Benchmarking the synchronized folders
Using dd
to read and write with block sizes 1KB, 4KB, and 16KB results in a workload similar to our compilation. The script for this experiment is provided near the end of this post. This test was run 3 times: all my results fell within 10% of one another. The host machine for this test was a 2013 MacBook Pro with an SSD, 16GB of RAM, and a 2.6 GHz Intel Core i7.
In this benchmark, “Native” refers to the native Virtualbox VM filesystem (which is not the same as the “Virtualbox” shared folder). It’s also useful to understand that the “RSync” shared folder is really a native folder in the VM – the only difference being that Vagrant exposes an easy to use vagrant rsync
call on the host machine which synchronizes to this folder.
It’s clear from this comparison that there is an order of magnitude of performance difference between the native filesystem and the Virtualbox and NFS shared folders. Here is another copy of the graph, with only the slower choices:
These artificial benchmarks correlate closely with our measured compilation times:
Virtualbox | NFS | NFS (UDP) | RSync | Native | |
Time (m:ss) | 4:35 | 2:38 | 4:15 | 0:30 | 00:31 |
The significantly faster compilation times on NFS vs Virtualbox lend credence to my assertion that our compilation’s reads and writes are mainly in the range of 0.5KB to 8KB, rather than 16KB+, where the Virtualbox shared folder has the lead.
Large block read/writes
Our workload doesn’t have many larger read/writes, but here’s a graph with those for anyone interested:
Conclusions
Vagrant’s shared folders are slow for intensive reads/writes of small files. It is an order of magnitude faster to use the native filesystem. At my current company, our workaround is to copy our source files from the shared folder into a temporary folder in the native filesystem, run the compilation there, and copy build artifacts back to the shared folder.
Vagrant’s RSync shared folders operate in a similar manner: they copy content from the host machine into a native folder in the VM. However, the mechanics of using the RSync shared folder (sync is done on user command, not automatically, and sync is one-way) make it unwieldy for our use case.
Each underlying technology for a Vagrant shared folder has some strengths which may be important for a certain application. The choice of shared folder should be tied to the use case for Vagrant.