17

I've got a Symfony 2.0 application running using Vagrant with a Linux guest and host O/S (Ubuntu). However, it runs slowly (e.g. several seconds for a page to load, often more than 10s) and I can't work out why. My colleagues who are running the site locally rather than on Vagrant VM have it running faster.

I've read elsewhere that Vagrant VMs run very slowly if NFS isn't enabled, but I have enabled that. I'm also using the APC cache to try and speed things up, but still the problems remain.

I ran xdebug against my site using the instructions at http://webmozarts.com/2009/05/01/speedup-performance-profiling-for-your-symfony-app, but I'm not clear where to start with analysing the data from this. I've got as far as opening it in KCacheGrind and looking for the high numbers under "Incl." and "Self", but this has just shown that php::session_start takes quite a long time.

Any suggestions as to what I should be trying here? Sorry for the slightly broad question, but I'm stumped!

Sam
  • 5,997
  • 5
  • 46
  • 66
  • 1
    Related: http://www.whitewashing.de/2013/08/19/speedup_symfony2_on_vagrant_boxes.html – Matthieu Napoli Aug 19 '13 at 12:36
  • That looks like a really good idea! I'm not using Vagrant any more, but I've let people here at work know. Some of them were using Vagrant, but I'm not sure if they still are. – Sam Aug 20 '13 at 09:31
  • 2
    Also highly related: http://www.erikaheidi.com/2013/09/24/optimizing-symfony-applications-vagrant-boxes/ – Sliq Jan 07 '14 at 16:53
  • A new thing in Vagrant 1.5 is [rsync support](https://www.vagrantup.com/blog/feature-preview-vagrant-1-5-rsync.html), which apparently offers "incredible I/O performance at the expense of a little bit of latency". I've not tried it, but it looks like it might help here. – Sam Jul 01 '14 at 14:35

5 Answers5

19

I've seen similar problem on my OS X host, I forgot to enable NFS! On windows Host, the performance impact is less true... For my very small website, I have kickly 12649 files... So the 1000+ files limit is quite easily reached.

So my two cents: enable NFS like this in your Vagrantfile:

config.vm.share_folder "v-root", "/vagrant", ".." , :nfs => true

And from the experts:

It’s a long known issue that VirtualBox shared folder performance degrades quickly as the number of files in the shared folder increases. As a project reaches 1000+ files, doing simple things like running unit tests or even just running an app server can be many orders of magnitude slower than on a native filesystem (e.g. from 5 seconds to over 5 minutes).

If you’re seeing this sort of performance drop-off in your shared folders, NFS shared folders can offer a solution. Vagrant will orchestrate the configuration of the NFS server on the host and will mount of the folder on the guest for you.

Note: NFS is not supported on Windows hosts. According to VirtualBox, shared folders on Windows shouldn’t suffer the same performance penalties as on unix-based systems. If this is not true, feel free to use our support channels and maybe we can help you out.

Edit:

On windows, I have found another solution, I am using symlinks (ln -fs) on vendor folders within my projects that links to non-shared folders. This reduce the amount of files seen by the windows host, the antivirus, etc.

Community
  • 1
  • 1
Alexandre Mélard
  • 12,229
  • 3
  • 36
  • 46
  • 1
    I use the following line in my Vagrantfile as that means it loads it for non-Windows (where it works) and not for Windows (where it doesn't): `config.vm.share_folder("v-root", "/vagrant", "./", :nfs => !RUBY_PLATFORM.downcase.include?("w32"))` – Sam Dec 05 '12 at 09:33
  • Did you try not to share the folder in vagrant and run a rsync job to push the files to the vagrant box? It's a bit tricky but if your response time improves a lot in return.. may be worth it – Alexandre Mélard Dec 07 '12 at 21:11
  • 1
    "The 'v-root' shared folders have been renamed to 'vagrant-root'" - Remember this if using a new version of Vagrant. – Scottymeuk Apr 08 '13 at 08:52
  • 1
    Note: With Vagrant 1.1 syntax, the line should be: `config.vm.synced_folder ".", "/vagrant", :nfs => !RUBY_PLATFORM.downcase.include?("w32")` – geerlingguy Aug 08 '13 at 13:21
  • great solution for windows is vagrant plugin: vagrant-winnfsd - enabling NFS for windows. – Tomek Kobyliński Sep 19 '14 at 05:43
  • Gives amazing performance boost on os x! Thanks :) You healed my life =) – Nikolay Fominyh Nov 28 '14 at 10:51
  • It reduced page load time from about 30 secons to 1.2 seconts! – Oscar Pérez Jan 16 '15 at 12:51
  • The OP clearly indicates that NFS is already enabled and yet performance is still unacceptable. I have confirmed this as well. Furthermore, I have confirmed that even with rsync enabled the latency persists. There is already plenty of documentation about Vagrant shared folder approaches, but information on the OPs particular use case, which appears to be prevalent, is sorely lacking. – Coder Guy Jun 08 '15 at 17:07
6

Where I work, we've tried out two solutions to the problem of Vagrant + Symfony being slow. I recommend the second one (nfs and bind mounts).

The rsync approach

To begin with, we used rsync. Our approach was slightly different to that outlined in AdrienBrault's answer. Rather, we had code like the following in our Vagrantfile:

config.vm.define :myproj01 do |myproj|
  # Networking & Port Forwarding
  myproj.vm.network :private_network, type: "dhcp"
  # NFS Share
  myproj.vm.synced_folder ".", "/home/vagrant/current", type: 'rsync', rsync__exclude: [
    "/.git/",
    "/vendor/",
    "/app/cache/",
    "/app/logs/",
    "/app/uploads/",
    "/app/downloads/",
    "/app/bootstrap.php.cache",
    "/app/var",
    "/app/config/parameters.yml",
    "/composer.phar",
    "/web/bundles",
    "/web/uploads",
    "/bin/behat",
    "/bin/doctrine*",
    "/bin/phpunit",
    "/bin/webunit",
  ]
  # update VM sooner after files changed
  # see https://github.com/smerrill/vagrant-gatling-rsync#working-with-this-plugin
  config.gatling.latency = 0.5
end

As you might notice from the above, we kept files in sync using the Vagrant gatling rsync plugin.

The improved NFS approach, using bind mounts (recommended solution)

The rsync approach solves the speed issue, but we found some problems with it. In particular, the one-way nature of it (as opposed to sharing folders) was annoying when files (like composer.lock or Doctrine migrations) were generated on the VM, or when we wanted to access code in /vendor. We had to SFTP in to copy things back - and, in the case of new files, do it before they were cleared by the next run of the gatling plugin!

Therefore, we moved to a solution which uses binding mounts to handle folders like cache and logs differently. Not having those shared increased the speed dramatically.

The relevant bits of the Vagrantfile are as follows:

# Binding mounts for folders with dynamic data in them
# This must happen before provisioning, and on every subsequent reboot, hence run: "always"
config.vm.provision "shell",
  inline: "/home/vagrant/current/bin/bind-mounts",
  run: "always"

The bind-mounts script referenced above looks like this:

#!/bin/bash

mkdir -p ~vagrant/current/app/downloads/
mkdir -p ~vagrant/current/app/uploads/
mkdir -p ~vagrant/current/app/var/
mkdir -p ~vagrant/current/app/cache/
mkdir -p ~vagrant/current/app/logs/

mkdir -p ~vagrant/shared/app/downloads/
mkdir -p ~vagrant/shared/app/uploads/
mkdir -p ~vagrant/shared/app/var/
mkdir -p ~vagrant/shared/app/cache/
mkdir -p ~vagrant/shared/app/logs/

sudo mount -o bind ~vagrant/shared/app/downloads/ ~/current/app/downloads/
sudo mount -o bind ~vagrant/shared/app/uploads/ ~/current/app/uploads/
sudo mount -o bind ~vagrant/shared/app/var/ ~/current/app/var/
sudo mount -o bind ~vagrant/shared/app/cache/ ~/current/app/cache/
sudo mount -o bind ~vagrant/shared/app/logs/ ~/current/app/logs/

NFS + binding mounts is the approach I'd recommend.

Sam
  • 5,997
  • 5
  • 46
  • 66
  • To clarify: We've used this will more recent versions of Symfony2 too, not just the version mentioned in my original question (2.0). – Sam Oct 08 '14 at 14:52
  • 2
    With the new layout of Symfony, you'll only need to bind mount `var` - anything that changes goes in there. See http://stackoverflow.com/a/23994473/3408 – rjmunro May 18 '15 at 15:29
5

ATM, basically, do not put your website code on the /vagrant shared folder. As it's shared between your VM and host O/S, it's slower; and I didn't find any efficient solution to get good performance. The solution we're using is to serve our developments apps from the classic /var/www, and keep them in sync with our local copy with rsync.

AdrienBrault
  • 7,747
  • 4
  • 31
  • 42
  • So you're still using the VM-creation capabilities of vagrant, just not the shared folder bit? Am I right that you're using rsync to sync the code on your host with /var/www on the guest instead? Just wanted to make sure I've understood what you're suggesting! Thanks – Sam Aug 29 '12 at 13:41
  • Okay, thanks. I will wait and see if anyone has any suggestions which allow me to continue using Vagrant in the standard way but, if not, I can investigate the option you mention. Thanks for your help. – Sam Aug 29 '12 at 14:49
  • In the end I went for running from my local machine rather than a VM at all, as that matches what the rest of the team are doing on this project, and I can re-use the local machine setup for other projects which will need it. Thanks for your input though, I may still try this in future. – Sam Aug 31 '12 at 08:37
  • @AdrienBrault are you able to keep the working copy and `/var/www` in sync automatically, or do you have to do that step manually? – shanethehat Mar 03 '13 at 09:07
  • 2
    @shanethehat I use PHPStorm and you can configure a remote server, and phpstorm to auto upload to it on file save – AdrienBrault Mar 03 '13 at 16:18
  • Vagrant now has built-in support for rsync https://docs.vagrantup.com/v2/synced-folders/rsync.html – Brian Ortiz Apr 19 '14 at 00:26
3

By following the instructions on this article Speedup Symfony2 on Vagrant boxes helped me out to solve this issue reducing the page loads from 6-10 seconds to 1 second on my Symfony2 project. Basically all the fix is to set the sync type between the host and the guest (the vagrant VM box) with NFS instead of using the VirtualBox shared folder system which is very slow.

Also adding this code below to AppKernel.php on the Symfony2 project, changes the cache and log directory to the shared memory directory (/dev/shm) on the vagrant box instead of writing those to the NFS share, so it improves the page load speed even better.

<?php

class AppKernel extends Kernel
{
    // ...

    public function getCacheDir()
    {
        if (in_array($this->getEnvironment(), array('dev', 'test'))) {
            return '/dev/shm/appname/cache/' .  $this->getEnvironment();
        }

        return parent::getCacheDir();
    }

    public function getLogDir()
    {
        if (in_array($this->getEnvironment(), array('dev', 'test'))) {
            return '/dev/shm/appname/logs';
        }

        return parent::getLogDir();
    }
}
elvismdev
  • 1,027
  • 11
  • 21
1

I use sshfs for sharing directories between host OS and VM (Expan drive for windows) It is much faster than native VBox directory sharing