Benchmark de frameworks PHP (CakePHP, Symfony2 y Yii)
29/Sep/2012
Hola a todos,
Hoy llueve y hace algo de frío. El otoño ha venido y, bueno, qué mejor que un poco de programación para pasar la tarde.
Entremos al punto a tratar en este post. He realizado un pequeño código con tres frameworks PHP de los más utilizados.
CakePHP es el framework que utilizo en mi día a día y que en cierto modo da buenos resultados,
pero que para proyectos de cierto tamaño puede llegar a quedarse corto.
Symfony2 es el framework de moda en el mundo PHP, el mejor en cuanto a calidad del código y aplicación de patrones de diseño.
Por otro lado, tenemos Yii puede que sea el más desconocido de los tres.
Yii me llamó la atención por la disponibilidad por la que presume, y por su organización modular al igual que Symfony2.
Probablemente el framework más fuerte que se ha quedado fuera ha sido Zend, básicamente por cuestiones de tiempo del autor :).
Bueno, entremos en matería. Se ha desarrollado un pequeño ejemplo que emula la típica petición ajax que hacemos para tomar una serie de datos del servidor, unos datos de productos de nuestra base de datos,
proporcionados por un servicio SOA.
Primero mostraremos el código de ejemplo desarrollado en cada framework. Al ser un problema tan pequeño, con mostrar el código del controlador y el del modelo en cuestión será suficiente en la mayoría de los casos.
CakePHP
Este es el código para CakePHP utilizando la versión 2.1.3
Modelo Product
Controlador SoaController
Como podemos ver el código es sencillo, simplemente con hacer una llamada find con el ORM de Cake y haciendo un json_encode conseguimos el resultado deseado.
Symfony2
En Symfony2 (versión 2.1.2), he utilizado como base el DemoBundle que viene con al instalación del framework.
No sé si esto puede haber influido en los resultados, a la vista de un no experto la cantidad de código aboga a un framework prácticamente vacío.
Entidad
Como se puede ver, se ha utilizado básicamente la clase generada por el asistente de consola del framework,
añadiendo un método toArray para hacer más fácil posteriormente la conversión a JSON.
Controlador
Como se puede ver, he tenido que hacer un foreach que puede haber supuesto un extra de carga, pero realmente no veía otro modo de solucionar el problema de la conversión
propiedades del objeto a JSON de manera más eficiente.
Yii
En Yii 1.1.12, a mi gusto la solución es la más elegante de todas. Sin demasiadas complicaciones como en Symfony2, ni demasiada directa y un poco sucia como en CakePHP.
A mi gusto, Yii es un framework realmente interesante y que ofrece una modularidad equiparable a los Bundles de Symfony2.
Modelo Product
Esta es la clase autogenerada por la herramienta Gii.
Para aquellos que no gustan del shell puede resultar más cómoda que el shell que lleva Symfony2, pero en mi opinión en este caso apoyo más la solución de Symfony,
ya que el shell acaba incrementando la productividad del desarrollador.
Controlador
En Yii, también he terminado por usar un bucle foreach para preparar la salida para la conversión JSON, aunque no utilicé un método toArray.
Estas diferencias sútiles pueden resultar algo críticas en un benchmark, aunque con una acción tan sencilla y teniendo detrás todo el código de un framework no me parecen muy significativas.
Bueno, ¿qué es un benchmark sin los datos de tiempos y demás? Ahora viene esa parte, antes quería exponer abiertamente el código para evitar malinterpretaciones y dejando claro que es un código muy básico,
por lo que los resultados no pueden aplicarse a una aplicación real en producción.
La configuración del servidor utilizada ha sido un servidor LAMP con las siguientes versiones:
Sistema Operativo
Ubuntu 12.04 LTS Linux 3.2.0-30-generic
Apache
Apache/2.2.22
MySQL Server
5.5.24
PHP
PHP 5.3.10-1ubuntu3.4 with Suhosin-Patch
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans
Como herramienta para el benchmark he utilizado siege. siege permite el benchmarking de una o varios URLs dada una concurrencia.
Estos son los resultados, de aplicar el siguiente comando con siege con diferentes configuraciones de Apache:
Veamos la primera tabla de resultados:
Modo desarrollo sin APC
CakePHP 2.1.3
Symfony 2.1.2
Yii 1.1.12
Transactions (hits)
1150 hits
152 hits
1191 hits
Availability
100%
100%
100%
Response time
0.13 s
0.96 s
0.12 s
Concurrency
4.97
4.96
4.99
Throughput
0.03 MB/s
0.00 MB/s
0.04 MB/s
Shortest Transaction
0.08 s
0.63 s
0.07 s
Longest Transaction
0.25 s
1.51 s
0.30 s
Bueno, por lo visto Yii Framework supera en velocidad al resto en modo desarrollo.
Aunque realmente, ¿quien despliega su aplicación en producción en modo desarrollo? Vamos pues a mostrar los datos poniendo cada uno de estos frameworks en modo producción.
Modo producción sin APC
CakePHP 2.1.3
Symfony 2.1.2
Yii 1.1.12
Transactions (hits)
1135 hits
265 hits
1353 hits
Availability
100%
100%
100%
Response time
0.13 s
0.54 s
0.11 s
Concurrency
4.99
4.95
4.99
Throughput
0.03 MB/s
0.01 MB/s
0.04 MB/s
Shortest Transaction
0.08 s
0.33 s
0.06 s
Longest Transaction
0.32 s
1.28 s
0.30 s
Symfony2 prácticamente duplica su rendimiento, mientras que Yii mejora un poco y CakePHP parece que su distinción entre modo desarrollo y modo producción es simplemente el error_reporting,...
Veamos ahora dándoles un poco más de caña
Modo producción sin APC (Concurrencia 50)
CakePHP 2.1.3
Symfony 2.1.2
Yii 1.1.12
Transactions (hits)
1104 hits
97 hits
1336 hits
Availability
100%
100%
100%
Response time
1.31 s
7.31 s
1.09 s
Concurrency
48.81
24.14
49.02
Throughput
0.03 MB/s
0.00 MB/s
0.04 MB/s
Shortest Transaction
0.15 s
0.85 s
0.11 s
Longest Transaction
2.35 s
25.23 s
1.72 s
Symfony2 da un rendimiento muy pobre con 50 clientes concurrentes, mientras que Yii y Cake más o menos se mantienen, no bajando en concurrencia pero sí en tiempo de respuesta.
Bueno, añadamos ahora una mejora importante al rendimiento del PHP. Vamos a añadir el módulo APC para ver como los distintos frameworks mejoran cuando el PHP tiene este módulo añadido.
Modo producción con APC
CakePHP 2.1.3
Symfony 2.1.2
Yii 1.1.12
Transactions (hits)
2358 hits
542 hits
2307 hits
Availability
100%
100%
100%
Response time
0.06 s
0.28 s
0.06 s
Concurrency
4.99
4.97
4.99
Throughput
0.07 MB/s
0.01 MB/s
0.07 MB/s
Shortest Transaction
0.03 s
0.19 s
0.03 s
Longest Transaction
0.41 s
0.58 s
0.16 s
La instalación ha sido crítica en todos los frameworks. La cantidad de código opcode cacheado por APC que no ha de volver a ser interpretado se nota con creces, teniendo todos los frameworks un aumento de rendimiento aproximadamente del 100%.
Pero volvamos a dar caña con concurrencia 50 :)
Modo producción con APC (Concurrencia 50)
CakePHP 2.1.3
Symfony 2.1.2
Yii 1.1.12
Transactions (hits)
2485 hits
517 hits
2429 hits
Availability
100%
100%
100%
Response time
0.60 s
2.74 s
0.60 s
Concurrency
49.41
47.51
49.42
Throughput
0.07 MB/s
0.01 MB/s
0.07 MB/s
Shortest Transaction
0.07 s
0.31 s
0.05 s
Longest Transaction
1.21 s
5.87 s
1.10 s
Finalmente podemos ver como Symfony2 con APC es capaz de mantener la concurrencia, aunque dando un tiempo de respuesto muy inferior al que Yii o CakePHP son capaces de responder.
Análisis
Mi análisis sobre estos datos es que Symfony2 sin usar Varnish como el proyecto propone, puede dar un rendimiento bastante pobre, mientras que Yii y CakePHP con la instalación de APC son capaces de dar un rendimiento aceptable.
Este aumento en rendimiento no justifica el no usar Symfony2, ya que es el framework mejor preparado para proyectos grandes, pero por este mismo motivo complica el desarrollo en equipos de pocas personas.
Finalmente, quería hacer notar la demasiada igualdad de rendimiento entre Yii y CakePHP. Cuando empecé el benchmark creía que Yii mejoraría mucho más el rendimiento de CakePHP, ya que por lo que se ve en el algunos benchmarks publicados, es mucho más rápido que este. En cambio, en este caso no se ha notado la diferencia.
Espero algún comentario que rebata este benchmark, sobretodo si viene de usuarios de Yii o Symfony2, para ver si hay algún punto en el que no se haya tratado en igualdad a estos frameworks con CakePHP.
Esto es todo por hoy, espero seguir dando actividad al blog y hablando de PHP, Javascript y Web en general.