Ver índice de contenidos del libro

18.3. Optimizando la vista

En función del diseño y la implementación realizada en la capa de la vista, se pueden producir mejoras o pérdidas de rendimiento en la aplicación. En esta sección se describen diferentes alternativas y sus inconvenientes.

18.3.1. Utilizando el fragmento de código más rápido

Si no se utiliza el mecanismo de cache, se debe tener en cuenta que include_component() es un poco más lento que include_partial(), que a su vez, es un poco más lento que un simple include de PHP. El motivo es que Symfony instancia una vista para incluir un elemento parcial e instancia un objeto de tipo sfComponent para incluir un componente, que a su vez requiere un procesamiento ligeramente superior al necesario para incluir directamente un archivo.

De todas formas, la pérdida de rendimiento es insignificante, a menos que se incluyan muchos elementos parciales o muchos componentes en una plantilla. Por tanto, este caso se puede dar en listados y en tablas o cuando se utiliza la llamada al helper include_partial() dentro de una sentencia foreach. Si se incluyen muchos elementos parciales o componentes en una plantilla y ello reduce notablemente el rendimiento de la página, se debería utilizar el mecanismo de cache (ver Capítulo 12) y si no es posible hacerlo, utilizar sentencias include de PHP.

En lo que respecta a los slots y a los slots de componentes, su diferencia de rendimiento sí que es apreciable. El tiempo de procesamiento necesario para incluir un slot es despreciable, ya que es equivalente al tiempo requerido para instanciar una variable. Sin embargo, los slots de componentes se basan en una configuración de la vista y necesitan instanciar unos cuantos objetos para funcionar. No obstante, los slots de componentes se pueden guardar en la cache de forma independiente a la plantilla, mientras que los slots siempre se guardan en la cache junto con la plantilla que los incluye.

18.3.2. Optimizando el sistema de enrutamiento

Como se explica en el capítulo 9, todas las llamadas a los helpers de enlaces realizadas por las plantillas utilizan el sistema de enrutamiento para transformar una URI interna en una URL externa. El proceso consiste en encontrar un patrón en el archivo routing.yml que coincida con la URI indicada. Symfony realiza este proceso de forma muy sencilla: comprueba la primera regla del sistema de enrutamiento y si no coincide con la URI interna, continua probando las siguientes reglas. Como cada comprobación requiere el uso de expresiones regulares, puede ser un proceso que consume mucho tiempo de procesamiento.

Afortunadamente, existe una solución muy sencilla: utilizar el nombre de la regla en vez de los pares modulo/accion. Con este método, se indica a Symfony qué regla debe utilizar y por tanto el sistema de enrutamiento no pierde tiempo intentando encontrar la regla que coincida con la URI.

Si se considera por ejemplo la siguiente regla de enrutamiento definida en el archivo routing.yml:

articulo_segun_id:
  url:          /articulo/:id
  param:        { module: articulo, action: leer }

En este caso, en vez de utilizar el siguiente enlace:

<?php echo link_to('mi articulo', 'articulo/leer?id='.$articulo->getId()) ?>

Se debería utilizar esta otra versión mucho más rápida:

<?php echo link_to('mi articulo', '@articulo_segun_id?id='.$articulo->getId()) ?>

Cuando la página incluye docenas de enlaces creados con reglas de enrutamiento, las diferencias se hacen muy notables.

18.3.3. Saltándose la plantilla

Normalmente, la respuesta se compone de una serie de cabeceras y el contenido, aunque algunas respuestas no necesitan contenidos. Las interacciones Ajax por ejemplo, normalmente sólo requieren enviar unos pocos datos desde el servidor a un programa de JavaScript que se encarga de actualizar diferentes partes de la página. En este tipo de respuestas muy cortas, es mucho más rápido enviar sólo las cabeceras. Como se vio en el Capítulo 11, una acción puede devolver una sola cabecera JSON. El listado 18-12 muestra el ejemplo del Capítulo 11.

Listado 18-12 - Ejemplo de acción que devuelve una cabecera JSON

public function executeActualizar()
  {
    $salida = '[["titulo", "Mi carta normal"], ["nombre", "Sr. Pérez"]]';
    $this->getResponse()->setHttpHeader("X-JSON", '('.$salida.')');
 
    return sfView::HEADER_ONLY;
  }

El código anterior no utiliza ni plantillas ni layout y la respuesta se envía de una sola vez. Como sólo contiene cabeceras, la respuesta es mucho más corta y tarda mucho menos en llegar hasta el navegador del cliente.

El Capítulo 6 explica otra forma de evitar el uso de las plantillas y devolver el contenido en forma de texto directamente desde la acción. Aunque esta técnica rompe con la separación impuesta por el modelo MVC, aumenta significativamente el capacidad de respuesta de una acción. El listado 18-13 muestra un ejemplo.

Listado 18-13 - Ejemplo de acción que devuelve el contenido directamente en forma de texto

public function executeAccionRapida()
{
  return $this->renderText("<html><body>Hola Mundo</body></html>");
}

18.3.4. Reduciendo los helpers por defecto

En cada petición se cargan los grupos de helpers estándar (Partial, Cache y Form). Si se está seguro de que no se van a utilizar los helpers de algún grupo, se puede eliminar este grupo de la lista de helpers estándar, lo que evita que se tenga que procesar el archivo del helper en cada petición. En concreto, el grupo de helpers de formularios (Form) es bastante grande y por tanto, ralentiza la ejecución de las páginas que no utilizan formularios. Por tanto, es una buena idea modificar la opción standard_helpers del archivo settings.yml para no incluirlo por defecto:

all:
  .settings:
    standard_helpers: [Partial, Cache]    # Se elimina "Form"

El único inconveniente es que todas las plantillas que utilicen formularios tienen que declarar explícitamente que utilizan los helpers del grupo Form mediante la instrucción use_helper('Form').

18.3.5. Comprimiendo la respuesta

Symfony comprime la respuesta antes de enviarla al navegador del cliente. Esta característica hace uso del módulo zlib de PHP. Si se quiere ahorrar el ligerísimo consumo de CPU que implica esta opción, se puede desactivar desde el archivo settings.yml:

all:
  .settings:
    compressed: off

Toda la mejora producida en la CPU se ve contrarrestada por una gran pérdida en el ancho de banda y en el tiempo de transmisión de la respuesta, por lo que esta opción no mejora el rendimiento en todas las aplicaciones.

Truco Si se desactiva la compresión en PHP, se puede habilitar en el nivel del servidor. Apache dispone de su propia extensión para comprimir los contenidos.