Как ускорить Vagrant (общие папки) > stdout.in Ievgen Kuzminov IT blog

Как ускорить Vagrant (общие папки)

14 нояб. 2015 г., 19:00:40

vagrant

Я разрабатываю PHP и Ruby веб приложения с использованием Vagrant и мне кажется, что это хорошее направление. Но есть одно "но" - плохая производительность веб приложений в Vagrant.
Основная проблема это низка скорость виртуализированной дисковой системы (папок с общим доступом между Хост машиной и Vagrant машиной).

Папки с общим доступом по-умолчанию

При стандартной конфигурации Vagrant-а, как
config.vm.synced_folder "./", "/var/www"
используется стандартный механизм папок с общим доступом в VirtualBox, но это работает медленно. И мы ощущаем последствия этого в виде медленного отклика веб приложений (это происходит из-за автоподгрузки классов и других операций связаных с диском).

Но есть пути улучшить это :

rsync

Если изменить конфигурацию на использование rsync
config.vm.synced_folder "./", "/var/www", type: "rsync"
то после vagrant reload
он не будет монтировать синхронизированную папку, а сделает физическое синхронизирование файлов в хранилище VirtualBox. Самое интересное, что внутренняя ФС VirtualBox очень быстрая (в отличии от ФС с общим доступом) и мы получаем очень хорошую производительность.

Но есть "ложка дегтя" :

  • для автоматизации синхронизации изменений с Хост машины на VB надо запускать vagrant rsync-auto каждый раз при запуске Vagrant машины

  • после каждого изменения файла проходит 2-3 сек. до синхронизации в VB

  • синхронизация односторонняя, нет нормальной возможности синхронизировать изменения обратно с VB на Хост машину (разработчики Vagrant обещали подумать над двусторонней синхронизацией, но пока это невозможно)

Так что на данный момент rsync не универсальный способ, но самый производительный.

NFS

Другой способ это использовать примонтированные NFS диски. Vagrant также поддерживает эту возможность
config.vm.synced_folder "./", "/var/www", type: "nfs"
и не забудьте запустить vagrant reload

После этого всё выглядит также, как и дисках с общим доступом по-умолчанию. Не надо ждать синхронизации или запускать синхронизацию вручную. Но производительность будет лучше (хотя и не такая, как при rsync).
Один минус - это не будет работать под Windows. А на Linux требуется установить спец. NFS пакет на Host и Vagrant машины.
На Host sudo apt-get install nfs-kernel-server nfs-common portmap.
На Vagrant sudo apt-get install nfs-common portmap.
Также NFS требует настроить в Vagrant Private network (а не public или bridget), должно быть примерно так
config.vm.network :private_network, ip: "10.10.11.11"

После единоразовой настройки всё будет работать автоматически и достаточно надежно. И это мой выбор на данный момент.

Иногда я встречал странные замедления при работе NFS в некоторых проектах. Пробуя разные параметры подключения, определил, что это может быть связано с локами файловой системы. И данная конфигурация улучшала производительность :
config.vm.synced_folder "./", "/var/www", type: "nfs", nfs_version: "4,nolock"

PHP opcode кэш (и подобные)

Ещё один аспект, который можно улучшить. использование opcode-ОЗУ кэша. Для PHP есть несколько вариантов - APC или Zend Opcache. Я не уверен, но для других скриптовых языков также могут быть подобные вещи. Например, включить APC кэш в Ubuntu можно так :
~~~ sudo apt-get install php-apc sudo service apache2 restart ~~~ В Vagrant машине вы увидете существенное ускорение PHP приложения с APC.

С другой стороны - рассматривайте это замедление работы диска в Vagrant, как хороший индикатор производительности вашего веб приложения. Если оно тормозит в Vagrant - возможно, будет тормозить и в Production :)

Автоматическая установка системных ресурсов

Не забывайте также настраивать CPU и RAM для лучшей производительности.
Благодарю stefanwrobel.com за рецепт по автоматизации этого.

config.vm.provider "virtualbox" do |v|
  host = RbConfig::CONFIG['host_os']

  # Даем VM 1/4 системной памяти & и доступ ко всем ядрам ЦП
  if host =~ /darwin/
    cpus = `sysctl -n hw.ncpu`.to_i
    # sysctl returns Bytes and we need to convert to MB
    mem = `sysctl -n hw.memsize`.to_i / 1024 / 1024 / 4
  elsif host =~ /linux/
    cpus = `nproc`.to_i
    # meminfo shows KB and we need to convert to MB
    mem = `grep 'MemTotal' /proc/meminfo | sed -e 's/MemTotal://' -e 's/ kB//'`.to_i / 1024 / 4
  else # увы, для Windows пользователей, возьмём некий дефолт
    cpus = 2
    mem = 1024
  end

  v.customize ["modifyvm", :id, "--memory", mem]
  v.customize ["modifyvm", :id, "--cpus", cpus]
end
comments powered by Disqus
Евгений
Кузьминов "iJackUA"
Web Team Lead
в MobiDev (Харьков, Украина)
Code in Ruby and Elixir, but still love PHP. Explore ES6 and Vue.js. Explore databases, use Ubuntu and MacOS, think about IT people and management

Заметки


SuperHeroJS - great collection of articles on all aspects of JavaScript. Starting from very basics up to questions of advanced usage, code organisation, testing, tools and performance