Successfully reported this slideshow.
Your SlideShare is downloading. ×

Por qué Symfony2 es tan rápido

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Ansible DevOps Day Peru 2016
Ansible DevOps Day Peru 2016
Loading in …3
×

Check these out next

1 of 38 Ad

More Related Content

Advertisement

Similar to Por qué Symfony2 es tan rápido (20)

Recently uploaded (20)

Advertisement

Por qué Symfony2 es tan rápido

  1. 1. Por qué Symfony2 es tan rápido Carlos Granados Carlos Granados
  2. 2. Por qué Symfony2 es tan rápido Carlos Granados
  3. 3. Por qué Symfony2 es tan rápido Carlos Granados
  4. 4. Por qué Symfony2 es tan rápido Carlos Granados
  5. 5. Por qué Symfony2 es tan rápido Carlos Granados • Crear el Kernel y leer la petición • Leer configuración • Compilar y cargar el contenedor de dependencias • Aplicar la configuración de seguridad • Leer todas las rutas definidas • Decidir qué ruta aplicar • Ejecutar al controlador apropiado • Leer la configuración de las entidades • Conectarse con la base de datos • Consultar la base de datos • Convertir los resultados de la base de datos en entidades • Construir las rutas que podamos necesitar • Encontrar qué plantilla twig usar • Compilar la plantilla twig • Ejecutar la plantilla twig • Convertir el resultado de la plantilla twig en una respuesta • Devolver esa respuesta al cliente • Autocargar todas las clases implicadas ¿Qué hace Symfony cuando recibe una petición?
  6. 6. Por qué Symfony2 es tan rápido Carlos Granados ¿Para cuándo dice que lo quiere?
  7. 7. Por qué Symfony2 es tan rápido Carlos Granados • Crear el Kernel y leer la petición • Leer configuración • Compilar y cargar el contenedor de dependencias • Aplicar la configuración de seguridad • Leer todas las rutas definidas • Decidir qué ruta aplicar • Ejecutar el controlador apropiado • Leer la configuración de las entidades • Conectarse con la base de datos • Consultar la base de datos • Convertir los resultados de la base de datos en entidades • Construir las rutas que podamos necesitar • Encontrar qué plantilla twig usar • Compilar la plantilla twig • Ejecutar la plantilla twig • Convertir el resultado de la plantilla twig en una respuesta • Devolver esa respuesta al cliente • Autocargar todas las clases implicadas Muchos de estos procesos están cacheados
  8. 8. Por qué Symfony2 es tan rápido Carlos Granados No hablamos del caché HTTP “La mejor petición es aquella que nunca llega a nuestro servidor”
  9. 9. Por qué Symfony2 es tan rápido Carlos Granados Hablamos del caché de aplicación app/cache
  10. 10. Por qué Symfony2 es tan rápido Carlos Granados app.php Entornos y depuración $kernel = new AppKernel('prod', false); app_dev.php $kernel = new AppKernel(‘dev', true); Entorno debug
  11. 11. Por qué Symfony2 es tan rápido Carlos Granados config_dev.ph web_profiler: toolbar: true El entorno se usa para saber qué fichero de configuración usar config_prod.ph web_profiler: toolbar: false Y también qué subdirectorio de app/cache utilizar app/cache/prod app/cache/dev
  12. 12. Por qué Symfony2 es tan rápido Carlos Granados El valor de debug es el que realmente distingue un entorno de depuración de uno de producción %kernel.debug% - Si se muestran los errores o no (en Symfony 2.3 está separado) - Si se actualiza la caché en cada ejecución
  13. 13. Por qué Symfony2 es tan rápido Carlos Granados Normalmente ‘prod’ = no debug y ‘dev’=debug Pero NO tiene por qué ser así Podemos, por ejemplo, crear un ‘app_staging.php’ con la configuración del entorno de producción pero con debug=true $kernel = new AppKernel('prod', true);
  14. 14. Por qué Symfony2 es tan rápido Carlos Granados APC “Sin APC Symfony no sería posible”
  15. 15. Por qué Symfony2 es tan rápido Carlos Granados APC: evitar que compruebe si tiene que recompilar ficheros apc.stat=0 en php.ini Al subir nuevo código hay que vaciar el caché APC: • Reiniciar el servidor • Crear un script que borre esta caché y ejecutarlo (con una llamada http)
  16. 16. Por qué Symfony2 es tan rápido Carlos Granados Autoload: como encuentra las clases el autoloader if (isset($this->prefixes[$first])) { foreach ($this->prefixes[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { return $dir . DIRECTORY_SEPARATOR . $classPath; } } } } } vendor/composer/ClassLoader.php
  17. 17. Por qué Symfony2 es tan rápido Carlos Granados Autoload: crear un classmap con Composer php composer.phar dump-autoload --optimize vendor/composer/autoload_classmap.php … 'AcmeDemoBundleAcmeDemoBundle' => $baseDir . '/src/Acme/DemoBundle/AcmeDemoBundle.php', 'AcmeDemoBundleControllerDemoController' => $baseDir . '/src/Acme/DemoBundle/Controller/DemoController.php', 'AcmeDemoBundleControllerSecuredController' => $baseDir . '/src/Acme/DemoBundle/Controller/SecuredController.php', 'AcmeDemoBundleControllerWelcomeController' => $baseDir . '/src/Acme/DemoBundle/Controller/WelcomeController.php', …
  18. 18. Por qué Symfony2 es tan rápido Carlos Granados Autoload: utilizar ApcClassLoader web/app.php // Use APC for autoloading to improve performance // Change 'sf2' by the prefix you want in order to prevent key conflict with another application $loader = new ApcClassLoader('sf2', $loader); $loader->register(true);
  19. 19. Por qué Symfony2 es tan rápido Carlos Granados Bootstrap app/bootstrap.php.cache • Construido por Composer durante la instalación • Se incluye en los front controllers • Contiene las clases básicas necesarias para inicializar el entorno Symfony: ContainerAwareInterface, Container, Kernel, Cl assCollectionLoader, ApcClassLoader, Bundle, ConfigCache, HttpKernel
  20. 20. Por qué Symfony2 es tan rápido Carlos Granados Classes.php app/cache/prod/classes.php • Se construye a partir de un mapa de clases: classes.map • En modo debug se comprueba cada clase del mapa para ver si ha cambiado y si es así se reconstruye el fichero classes.php • En modo no debug sólo se construye classes.php si no existe
  21. 21. Por qué Symfony2 es tan rápido Carlos Granados Classes.map app/cache/prod/classes.map Contiene las clases que cada bundle decida incluir para optimizar $this->addClassesToCompile(array( 'Twig_Environment', 'Twig_Extension', 'Twig_Extension_Core', 'Twig_Extension_Escaper', 'Twig_Extension_Optimizer', 'Twig_LoaderInterface', 'Twig_Markup', 'Twig_Template', )); Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
  22. 22. Por qué Symfony2 es tan rápido Carlos Granados Classes.map app/cache/prod/classes.map Podemos añadir clases de nuestros bundles public function load(array $configs, ContainerBuilder $container) { … $this->addClassesToCompile(array( 'AcmeDemoBundleTwigExtensionDemoExtension', 'AcmeDemoBundleTwigEventListenerControllerListener', )); } Acme/DemoBundle/DependencyInjection/AcmeDemoExtension.php
  23. 23. Por qué Symfony2 es tan rápido Carlos Granados Contenedor de dependencias app/cache/prod/appProdProjectContainer.php • Lo construye el compilador del contenedor de dependencias • En modo debug se comprueba un fichero appDevDebugProjectContainer.php.meta generado al compilar. Si alguna de las clases incluidas ha cambiado, regeneramos el contenedor • En modo no debug sólo se construye el contenedor si no existe
  24. 24. Por qué Symfony2 es tan rápido Carlos Granados Contenedor de dependencias … /** * Gets the 'doctrine' service. * * This service is shared. * This method always returns the same instance of the service. * * @return DoctrineBundleDoctrineBundleRegistry A DoctrineBundleDoctrineBundleRegistry instance. */ protected function getDoctrineService() { return $this->services['doctrine'] = new DoctrineBundleDoctrineBundleRegistry($this, array( 'default' => 'doctrine.dbal.default_connection'), array( 'default' => 'doctrine.orm.default_entity_manager'), 'default', 'default'); } … app/cache/prod/appProdProjectContainer.php
  25. 25. Por qué Symfony2 es tan rápido Carlos Granados Enrutador app/cache/prod/appProdUrlMatcher.php • Lo construye el componente de enrutación • En modo debug se comprueba un fichero appDevUrlMatcher.php.meta generado por el router. Si alguno de los recursos (ficheros yml, controladores, etc…) incluidos ha cambiado, regeneramos el enrutador • En modo no debug sólo se construye el enrutador si no existe
  26. 26. Por qué Symfony2 es tan rápido Carlos Granados if (0 === strpos($pathinfo, '/_')) { // _wdt if (0 === strpos($pathinfo, '/_wdt') && preg_match('#^/_wdt/(?P<token>[^/]++)$#s', $pathinfo, $matches)) { return $this->mergeDefaults(array_replace($matches, array('_route' => '_wdt')), array ('_controller' =>'web_profiler.controller.profiler:toolbarAction',)); } app/cache/prod/appProdUrlMatcher.php Enrutador Es importante que las rutas más usadas estén al principio: • Definirlas antes en los ficheros yml • Definirlas antes en los controladores si usamos anotaciones
  27. 27. Por qué Symfony2 es tan rápido Carlos Granados # app/config/config_prod.yml parameters: router.options.matcher.cache_class: ~ # disable router cache router.options.matcher_class: SymfonyComponentRoutingMatcherApacheUrlMatcher Usar el Enrutador de Apache $ php app/console router:dump-apache -e=prod --no-debug # skip "real" requests RewriteCond %{REQUEST_FILENAME} -f RewriteRule .* - [QSA,L] # hello RewriteCond %{REQUEST_URI} ^/hello/([^/]+?)$ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:hello,E=_ROUTING_name:%1,E=_ROUTING__controller: AcmeDemoBundle:Demo:hello] // web/app.php … use SymfonyComponentHttpFoundationApacheRequest; … $kernel->handle(ApacheRequest::createFromGlobals())->send();
  28. 28. Por qué Symfony2 es tan rápido Carlos Granados static private $declaredRoutes = array( '_demo' => array ( 0 => array ( ), 1 => array ( '_controller' => 'AcmeDemoBundleControllerDemoController::indexAction', ), 2 => array ( ), 3 => array ( 0 => array ( 0 => 'text', 1 => '/demo/', ), ), 4 => array ( ),), '_demo_hello' => array ( 0 => array ( 0 => 'name', ), 1 => array ( '_controller' => 'AcmeDemoBundleControllerDemoController::helloAction', ), 2 => array ( ), 3 => array ( 0 => array ( 0 => 'variable', 1 => '/', 2 => '[^/]++', 3 => 'name', ), 1 => array ( 0 => 'text', 1 => '/demo/hello', ), ), 4 => array ( ),), … app/cache/prod/appProdUrlGenerator.php Enrutador: generador de rutas
  29. 29. Por qué Symfony2 es tan rápido Carlos Granados Plantillas app/cache/prod/templates.php • Lo construye un caché warmer del componente de plantillas • En modo debug no se construye • Hay un directorio app/cache/prod/twig donde están las plantillas compiladas. En modo no debug sólo se genera cada plantilla si no existe. • La estructura del directorio Twig es un poco rara. Puede ser dificil encontrar la plantilla compilada. Usar una búsqueda global por ficheros con el nombre de la plantilla.
  30. 30. Por qué Symfony2 es tan rápido Carlos Granados return array ( … 'AcmeDemoBundle:Demo:index.html.twig' => '/Z:/stack/src/Acme/DemoBundle/Resources/views/Demo/index.html.twig', 'AcmeDemoBundle:Demo:hello.html.twig' => '/Z:/stack/src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig', '::base.html.twig' => '/Z:/stack/app/Resources/views/base.html.twig', ); app/cache/prod/templates.php Plantillas // line 5 public function block_content($context, array $blocks = array()) { // line 6 echo " <h1>Hello "; echo twig_escape_filter($this->env, (isset($context["name"]) ? $context["name"] : null), "html", null, true); echo "!</h1>"; }
  31. 31. Por qué Symfony2 es tan rápido Carlos Granados Otros elementos en el cache • Anotaciones • Traducciones • Assetic • Doctrine • Etc… Muchos de estos elementos se crean con un cache warmer.
  32. 32. Por qué Symfony2 es tan rápido Carlos Granados SymfonyComponentHttpKernelCacheWarmerCacheWarmerInterface Crear un cache warmer para tu bundle public function warmUp($cacheDir) { // Creamos el contenido a guardar el el cache $content = ...; // Lo guardamos en el cache $this->writeCacheFile($cacheDir.'/filename.php', $content); } public function warmUp($cacheDir); public function isOptional(); SymfonyComponentHttpKernelCacheWarmerCacheWarmer
  33. 33. Por qué Symfony2 es tan rápido Carlos Granados • Query cache • Metadata cache • Result cache Cache de Doctrine doctrine: orm: metadata_cache_driver: apc query_cache_driver: type: service id: my_doctrine_common_cache_service result_cache_driver: type: memcache host: localhost port: 11211 instance_class: Memcache …
  34. 34. Por qué Symfony2 es tan rápido Carlos Granados • Hacer un cache:clear (con warmup) cada vez que instalemos en producción • apc.stat=0 en php.ini • Crear un classmap con Composer • Activar ApcClassLoader • Listar las clases que queremos añadir a classes.map en nuestro bundle • Ordenar las rutas para que las más usadas aparezcan antes • Usar el enrutador de Apache • Crear cache warmers con ficheros inicializados por nuestro bundle Conclusiones
  35. 35. Por qué Symfony2 es tan rápido Carlos Granados
  36. 36. Por qué Symfony2 es tan rápido Carlos Granados ¡¡Gracias!! • carlos@planetapluton.com • @carlos_granados • http://es.linkedin.com/in/carlosgranados ¿Preguntas? • https://joind.in/8852

×