Rendimiento de constantes en PHP

En PHP tengo por costumbre el usar variables globales como constantes, pero no ha sido hasta hace bien poco que me he cuestionado su eficiencia, teniendo en cuenta que existe define.

Pensando de manera análoga a C, suponía que define iba a ser mucho más eficiente, al ser una constante definida en tiempo de interpretación. Nada más sencillo que comprobarlo con el siguiente código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
	$KI_MAX_ITER = 1000;
	define('KI_MAX_ITER', 1000);
 
	$fInicio=microtime(true);
	for ($iCont1=0; $iCont1<$KI_MAX_ITER; $iCont1++)
	{
		for ($iCont2=0; $iCont2<$KI_MAX_ITER; $iCont2++)
		{
			$iCont3=($KI_MAX_ITER != $KI_MAX_ITER);
			$iCont3=$KI_MAX_ITER;
			$iCont3=($KI_MAX_ITER == $KI_MAX_ITER);
		}
 
	}
	$fFin=microtime(true);
	echo ($fFin - $fInicio) . '<br>';
 
	$fInicio=microtime(true);
	for ($iCont1=0; $iCont1<KI_MAX_ITER; $iCont1++)
	{
		for ($iCont2=0; $iCont2<KI_MAX_ITER; $iCont2++)
		{
			$iCont3=(KI_MAX_ITER != KI_MAX_ITER);
			$iCont3=KI_MAX_ITER;
			$iCont3=(KI_MAX_ITER == KI_MAX_ITER);
		}
 
	}
	$fFin=microtime(true);
	echo ($fFin - $fInicio) . '<br>';
?>

El resultado es que usar una varíable de ámbito global ha llevado 0.41 segundos, mientras que hacerlo con define 0.89. En conclusión, a la hora de usar constantes, evita define siempre que sea posible, usando en su defecto variables globales.

Actualizado a martes 22 de marzo de 2011. 8:14:
Aclarando el apunte de Fernando, debo indicar que las pruebas iniciales protagonistas de este artículo se efectuaron con una versión algo antigua de PHP, la 5.2.3 que es la que tenía en mi servidor de desarrollo.

Tras actualizar a PHP 5.3.6, los resultados obtenidos han sido bien distintos: 0.18 para define, y 0.64 para variable global. Por tanto vemos que la rama 5.3.x es más rápida que la 5.2.x, pero sobre todo, vemos que han cambiado las tornas, y que se confirma lo comentado por Fernando. Es más veloz el uso de define.

Es el resultado lógico que cabría esperar, y que sólo puedo atribuir a un bug en implementaciones anteriores de PHP.



7 comentarios en “Rendimiento de constantes en PHP”

  1. Supongo que el motivo por el cual en este caso es mas rapido usar la variable local es que la cache L1 del procesador acceda rapidamente al dato, haciendo que el overheat que pueda causar el uso de la constante (buscar cada vez en la tabla de constantes la constante especifica), el cual es hecho muy posiblemente en tiempo de compilacion (por lo tanto, se podria cachear con APC) supera la ganancia ganada.

    Lo mejor para hacer este benchmarck seria usar algun ejemplo real, para realmente poder ver la diferencia. Aparte, te recomendaria probar de hacer el benchmark con y sin un sitema de cache de byte-code para ver el impacto que podria tener.

  2. Qué versión de PHP has probado?

    e:\usr\php-5.2.13>php ..\global.php
    0.66606092453003
    1.6308879852295

    e:\usr\php-5.3.6>php ..\global.php
    0.32651901245117
    1.6706237792969

    Otra cosa, el Firefox me carga tu página como ISO-8859-1 cuando es UTF-8…

  3. Fernando, he actualizado el artículo en base a tus comentarios, y debo decirte que en versiones recientes de PHP, los números están en la linea de lo que indicas. Mis pruebas se efectuaron con versiones antiguas/obsoletas de PHP, y los resultados obtenidos inicialmente parecen no ser relevantes.

    En cuanto a los problemas de encoding, voy a pegarle un repaso para solucionarlo. Gracias por el reporte.

  4. Creo que te has colado con los números… el primer valor es el del bucle que utiliza variable global mientras que el segundo es el del define…

    Lo curioso es que si bien la velocidad se ha incrementado mucho de la rama 5.2 a la 5.3 se ve un comportamiento muy particular:
    En el bucle con variable global la diferencia de velocidad según la versión es muy significativa.
    En el bucle con define la diferencia de velocidad no es apenas significativa.

  5. A mi también me llamó la atención ese aspecto Fernando, que he atribuido a un bug en PHP 5.2.3, sin embargo, bien pudiera ser que se haya ido optimizando el comportamiento de define.

    En todo caso, es algo que requeriría ir probando con PHP 5.2.3 hasta 5.2.13 para ver si ha sido una evolución o algún tipo de bug.

    Lo que es un hecho es que la implementación de 5.3, mejora sobremanera con define, que para mi es como debería ser.

  6. Actualizando datos:
    c:\usr>php-5.5.38\php global.php
    Global: 0.074177026748657
    Define: 0.085258960723877
    c:\usr>php-5.6.36\php global.php
    Global: 0.070980072021484
    Define: 0.086916208267212
    c:\usr>php-7.0.30\php global.php
    Global: 0.041682004928589
    Define: 0.077543020248413
    c:\usr>php-7.1.12\php global.php
    Global: 0.044300079345703
    Define: 0.071455955505371
    c:\usr>php-7.2.6\php global.php
    Global: 0.044541120529175
    Define: 0.073884010314941

    Hay que tomar en consideración que para tener unos datos más consistentes se debería repetir cada prueba un buen número de veces y sacar las pertinentes estadísticas… pero para una referencia básica valen.
    Una lectura interesante es que si bien se pregona que la velocidad de php ha mejorado mucho de versión a versión, se ha valorado dicha mejora con aplicaciones «reales» (distintos CMS como WordPress o Drupal y frameworks distintos) y no con test específicos como este.
    En este test se ve una mejora en cuanto al bucle con variables globales en el salto de php-5 a php-7, el resto de valores es bastante estable.

Deja un comentario