Publi

El método más rápido para traer un valor pasado por $_GET [ PHP ]

Tal vez por paranoia, por ganas de perder el tiempo, o por optimizar aún más el código fuente nos encontremos ante esta cuestión.

He realizado una serie de pruebas para ver cuál es el método que mejor funciona para traer un valor de $_GET basándome en el peor de los casos: cuando este valor no existe. Tal vez las pruebas no tengan excesiva validez por el método utilizado, aunque he intentado hacer todas las pruebas en las mismas condiciones.

Las medidas de tiempo han sido tomadas con el comando time de la siguiente manera:

$ time php myscript.php

Se han hecho un total de 7 pruebas, 1 de ellas de control. Las pruebas se han basado en la generación de cadenas aleatorias (que más tarde serán nuestro parámetro $_GET), además, la obtención del parámetro ha sido hecha unas 500000 veces con un bucle for. Se detallan las pruebas realizadas.
Cada prueba se ha repetido tres veces y se ha capturado el tiempo de las tres veces. Estamos usando un software complicado que hará muchas cosas mientras se realiza el test, es más, el sistema operativo puede requerir hacer una tarea que puede influir en nuestro resultado, por lo que así minimizamos el error (y si en alguna ocasión sale un dato desorbitado podemos descartarlo).

Prueba de control [TEST 0]

La generación de parámetros es lo que más tarda. Se ha utilizado uniqid() para obtener cadenas de la misma longitud y contenido arbitrario y diferente cada vez. Además, tanto la obtención del parámetro (en las siguientes pruebas) como la generación del nombre del parámetro se hace un número N de veces gracias a un bucle (que también invierte un tiempo).

Con esta prueba de control podremos ver en qué grado son significativos los valores obtenidos luego (cuando hagamos la obtención de datos), ya que vemos que el bucle y la generación tardan de media 4.493 segundos.

El código fuente del script para esta prueba es el siguiente:

1
2
3
4
5
echo "Probando 500000 peticiones GET";
for ($i=0; $i<500000; $i++)
{
$getVar=uniqid();
}

Anulando error_reporting() [TEST 1]

Lo que nos impide hacer un $variable=$_GET[‘parametro’]; es el error_reporting, ya que si éste no existe, nos devolverá un feo error por pantalla. Así que probemos primero desactivando esto y obteniendo el valor de la variable.

1
2
3
4
5
6
7
echo "Probando 500000 peticiones GET";
error_reporting(E_NONE);
for ($i=0; $i<500000; $i++)
{
$getVar=uniqid();
$dato=$_GET[$getVar];
}

Con @$_GET[…] [TEST 2]

Otra manera de impedir que PHP muestre sus errores en pantalla, es colocando una @ delante de lo que creemos que puede fallar, y en este caso es la sentencia de $_GET[$getVar].

1
2
3
4
5
6
7
echo "Probando 500000 peticiones GET";

for ($i=0; $i<500000; $i++)
{
$getVar=uniqid();
$dato=@$_GET[$getVar];
}

if…else [TEST 3]

No es nada intuitivo, PHP es un lenguaje de scripting, así que cuanto más escribamos, peor, pero merece la pena hacer la prueba, y nos podemos llevar una sorpresa. Ahora, hacemos la obtención del dato, pero primero comprobamos que éste existe con isset().

1
2
3
4
5
6
7
8
9
echo "Probando 500000 peticiones GET";
for ($i=0; $i<500000; $i++)
{
$getVar=uniqid();
if (isset($_GET[$getVar]))
$dato=@$_GET[$getVar];
else
$dato=false;
}

Operador ternario ? [ TEST 4 ]

Tal vez vaya mejor que el if…else (TEST 3), por aquella razón de escribir menos que comentaba…

1
2
3
4
5
6
echo "Probando 500000 peticiones GET";
for ($i=0; $i<500000; $i++)
{
$getVar=uniqid();
$dato=(isset($_GET[$getVar]))?$_GET[$getVar]:false;
}

Creando una función auxiliar gval() [ TEST 5 ]

Tal vez escribimos más que con el TEST 2 pero, vamos a probar, qué tal va. Tal vez si la diferencia de tiempo no es significativa podemos utilizar este método…

1
2
3
4
5
6
7
8
9
10
11
function gval($getVar)
{
return (isset($_GET[$getVar]))?$_GET[$getVar]:false;
}

echo "Probando 500000 peticiones GET";
for ($i=0; $i<500000; $i++)
{
$getVar=uniqid();
$dato=gval($getVar);
}

Función auxiliar y parámetro por referencia [ TEST 6 ]

Una nueva prueba, ya que hemos hecho una función auxiliar, veamos cómo influye el pasar el parámetro por valor o pasarlo por referencia. En este caso podríamos hacerlo sin problema.

1
2
3
4
5
6
7
8
9
10
11
function gval(&amp;$getVar)
{
return (isset($_GET[$getVar]))?$_GET[$getVar]:false;
}

echo "Probando 500000 peticiones GET";
for ($i=0; $i<500000; $i++)
{
$getVar=uniqid();
$dato=gval($getVar);
}

Resultados obtenidos

Tipo de pruebaPrimer resultadoSegundo resultadoTercer ResultadoMedia
TEST 04,45304,59604,43104,4933
TEST 16,75606,13905,83506,2433
TEST 27,38807,33507,31207,3450
TEST 35,52704,99005,06105,1927
TEST 45,44804,98205,10605,1787
TEST 56,28606,40505,81606,1690
TEST 65,98405,62905,74405,7857

Con estos resultados podemos observar que:

  • Efectivamente, el test de control es el más lento, incluye generación del nombre aleatorio del parámetro, el bucle y la carga del programa (PHP), pero más o menos partimos de que el tiempo mínimo para esta prueba son cerca de 4.5 segundos. El tiempo de obtención de dato, será más o menos la diferencia entre el tiempo total del test y los 4.5 segundos aproximadamente obtenidos aquí.
  • TEST 1: error_reporting(E_NONE) nos entorpecería en tareas de depuración (cuando realmente deseemos tenerlo en otro valor), de todas formas no es una opción, comparado con los demás. Deberíamos estar pendientes del valor de error_reporting() cuando queramos depurar el script, no ahorraríamos mucho código y tampoco es el mejor con respecto al tiempo.
  • TEST 2: Estaría bien que un carácter nos solucionara la vida, pero no es así… conseguimos el peor tiempo de todos. Se ve que a PHP le sienta mal cuando no encuentra una variable…
  • TEST 3 y TEST 4: Parece que un if…else nos puede ayudar a hacer nuestro código más rápido, un poco más elegante y funcionar mejor. También vemos que el operador ? puede ayudar. Y vemos, además, que el tiempo entre if…else y entre ? es el mismo (la diferencia es despreciable en este caso)
  • TEST5: Visto lo visto con TEST3 y TEST4 en los que escribimos más que con TEST2, vamos a crear una función auxiliar, a ver cómo se comporta con respecto a lo que tenemos. Comprobamos que el uso de una función, hace nuestro código más claro (punto positivo) y aún tarda menos que TEST1 y TEST2 aunque tarda algo más que TEST3 y TEST4. TEST5 tarda aproximadamente lo que TEST1.
  • TEST6: Parece que el hecho de no copiar el valor de una variable de verdad influye significativamente en el tiempo cerca de medio segundo; podemos seguir utilizando un método elegante con nuestra función auxiliar y al mismo tiempo aproximarnos a un tiempo mínimo.
  • Sé que 500000 iteraciones puede parecer exagerado aunque en momentos de carga de servidor y cuando esperamos que nuestra página tenga un número importante de visitas tal vez se agradezca un poco de agilidad, sobre todo en recepción de formularios (con variables $_POST). De todas formas, queda claro con estas pruebas que el hecho de poner una @ en un comando o asignación, sólo hace que PHP se trague los errores, pero es un método lento, con lo que podemos empezar a optimizar nuestro código por ahí.

También podría interesarte...

There are 4 comments left Ir a comentario

  1. Pingback: Bitacoras.com /

  2. Pingback: BlogESfera.com /

  3. Angelverde /
    Usando Mozilla Firefox Mozilla Firefox 3.6.13 en Linux Linux

    Me pase un rato leyendo los articulos de la categoria PHP, esos me gustan.

    Un saludo.

  4. Pingback: Comparativa de acceso rápido y seguro a un elemento de un array unidimensional [PHP] – Poesía Binaria /

Leave a Reply