Why is my Symfony 2.0 site running slowly on Vagra

2020-02-17 09:42发布

问题:

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!

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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();
    }
}


回答5:

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