Improving the performance of synced folders in Vagrant

For developers working with files inside Vagrant, you might not be aware that the default synced folder configuration is slow for large files and folders.

We encountered this problem when working with Symfony projects and it seems to be a known issue with Vagrant.

Benchmark

Below is the specs and setup of the machine used for the test environment.

[Host]
MacBook Pro 13" 2016
OS: macOS 10.14.5 (Mojave)
CPU: Intel Core i5 2.0 GHz
RAM: 8 GB 1867MHz LPDDR3

[Guest]
OS: Ubuntu 16.04 (Xenial), Linux Kernel 4.4.0
vCPU: 2
vRAM: 2GB

[Synced Folder]
Symfony-based Project with Node.js
Disk Usage: 542MB
Items: 65,225
var: 210MB (4973 files)
node_modules: 171MB (32,092 files)
vendor: 140MB (24,070 files)

We can measure the I/O performance by running a find . command inside the synced folder of the virtual machine.

bizwind@macbook-pro:~$ vagrant ssh
vagrant@ubuntu-xenial:~$ cd /vagrant && time find .  > /dev/null
real    0m11.775s
user    0m0.012s
sys     0m6.936s

The find process took about 11.77 seconds to complete. In the host, it took only 0.70 second.

Solutions

To improve our Vagrant box’s performance, we discovered the following tricks:

NFS (Network File System)

NFS does not work on Windows hosts.

This option attaches and shares the target directory and files with your virtual machine over a network.

It is faster than the default VirtualBox filesystem but not as fast as the native filesystem.

Prerequisites

Enabling NFS Synced Folders

Simply add type: "nfs" flag onto your synced folder:

# Vagrantfile
config.vm.synced_folder ".", "/vagrant", type: "nfs"

Permissions

Running a Vagrant machine with NFS requires an administrator password to modify the hosts files.

macOS Mojave

The NFS exports breaks in macOS Mojave. To fix this, open System Preferences > Security & Privacy > Privacy and add your terminal app (or any app that you use to launch Vagrant) to Full Disk Access and Accessibility.

Security & Privacy Settings FDA Screenshot

Security & Privacy Settings Accessibility Screenshot

You can find the discussion about this on this GitHub issue.

Caveats

NFS sync comes with some quirks that you need to watch out for.

Delayed sync

When editing files in the host, there will be some delays before the changes show up in the guest. To increase sync speed, lower actimeo (attribute caching timeout) mount option to 2 or 1 second.

config.vm.synced_folder ".", "/vagrant",
    type: "nfs",
    mount_options: ['actimeo=2']

You can set actimeo to 0 (disabled) to guarantee faster sync but it will decrease performance through additional latency, network load, and server load.

File Watchers

File watchers like gulp-watch or gradle --continuous running inside the VM won’t be able to detect changes when files are edited on the host because the inotify API that they commonly use doesn’t work with NFS-mount directories. There are workarounds for this:

Polling

Polling actively waits for one of a set of file descriptors to become ready to perform I/O. This is the simplest solution if your build tool supports it.

Here are some sample configurations:

// Webpack
module.exports = {
    watchOptions: {
        poll: 1000 // Check for changes every second
    }
};

// Gulp
const { watch } = require('gulp');
watch(['input/*.js', '!input/something.js'], { 'usePolling': true }, function(cb) {
    cb();
});

Vagrant Plugins

If polling is not an option, these plugins can help. These require installation and restart of the virtual machine.

Benchmark

With NFS, running the same find . command took 5.12 seconds to complete – about 78% faster than the default VirtualBox shared folder.

vagrant@ubuntu-xenial:/vagrant$ time find . > /dev/null
real    0m5.121s
user    0m0.060s
sys     0m1.944s

Avoid syncing large folders

The temporary, cache, and package directories usually contain the most number of files in a project. If possible, moving these directories outside the sync folder can further help reduce the sync load and improve the performance of your virtual machine.

Heaviest objects in the universe meme


References