on
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
- The host machine must have
nfsd
(NFS server daemon) installed. - The guest machine must have NFS support installed. Vagrant usually sets this up automatically. If not,
install it using the guest OS' package manager (yum
,apt
, etc.) - Private network setup if using VirtualBox as the provider.
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.
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.
- vagrant-notify-forwarder - forwards filesystem events
from the host to the guest automatically on all shared folders. - vagrant-fsnotify - runs a process for listening for
filesystem events on the host and, when a notification is received, runstouch
orrm
inside the vm, causing
an event to be propagated on the guest filesystem.
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.
References
- Network File System (NFS)
- NFS - Synced Folders - Vagrant by HashiCorp
- NFS and Oracle - Mount Options
- Watch and WatchOptions - Webpack
- watch() - gulp.js
- Speed up Vagrant Synced Folders