Una de las curiosidades dentro del mundo PHP es que existe un tiempo máximo definido para realizar consultas al servidor. Ésta, como otra más; es una medida de seguridad y de depuración.

Si tuvieramos un script en PHP que hace una consulta a una base de datos y ésta tarda más de lo esperado, podríamos quedarnos delante de la pantalla durante un buen rato. Y aún peor si realizaramos peticiones con AJAX, donde la respuesta debería ser en tiempo real. Es por ello que los servicios arrojados por el servidor deben ser inmediatos, o por lo menos con una duración inapreciable. Según el tipo de aplicación; este tiempo debería ser de segundos, pero existen otras muchas aplicaciones que para inicializar por ejemplo una sesión tardan un rato de unos 10 segundos aprox, y a partir de ahí todo funciona de forma fluida. O al menos se intenta.

Vamos a exponer un ejercicio en el que puede ocurrir este caso y se aplicará a posteriori para otro fin. Se trata de crear un script con PHP que introduzca millones de registros en una base de datos a partir de un archivo de texto; también creado con PHP. Así que para ello vamos a crear una carpeta llamada “Entries” donde crearemos un archivo de texto y el script PHP “createEntries.php” escribirá sobre este archivo de texto.

El nombre del archivo de texto a crear será “Entries10M.txt


<?php

function randfloat(){
return mt_rand() / mt_getrandmax();
}

$num=10000000;
$nfile='10M';

$file_src= 'Entries'.$nfile.'_'.txt';
if (!is_file ( $file_src )){
echo 'No file'.'<br>';
}
$file = fopen($file_src,"a");

for ($i=0; $i < $num; $i++) {
$String = strval(randfloat()*100).','.strval(randfloat()*100);
//echo strval(randfloat()*100).','.strval(randfloat()*100);
//echo '<br>';
fputs($file, $String);
fputs($file, "\r\n");
}

fclose($file);

?>

Una vez hecho esto, solo tendremos que dirigirnos a la página del script “createEntries.php” y comenzará a ejecutar el bucle para introducir datos dentro del archivo.

Pero para sorpresa nuestra cuando lleve un tiempo; pueden ser 30 segundos o 2 minutos, el script dejará de funcionar con el siguiente mensaje de error.

TimeExceededEsto es debido a una variable creada por defecto en php definida como max_execution_time.

Esta variable se puede cambiar accediendo al archivo de configuración php.ini y modificando esta variable por un número más largo.

Por otra parte esta variable tambien puede ser modificada a través del propio script de ejecución permitiendo que nuestro script tarde más en terminar. set_time_limit().

Con esta función permitimos que nuestro script extienda su uso durante el tiempo determinado entre paréntesis. Si lo dejamos vacio, se considera que el script puede estar ejecutándose indefinidamente.


<?php
set_time_limit(400);
function randfloat(){
return mt_rand() / mt_getrandmax();
}

try{

set_time_limit(400);
$num=10000000;
$nfile='10M';

$file_src= 'Entries'.$nfile.'_'.date("m").'_'.date("Y").'.txt';
if (!is_file ( $file_src )){
throw new PathException('Exception: File '.$file_src.' not exists', 200);
}
$file = fopen($file_src,"a");

for ($i=0; $i < $num; $i++) {
$String = strval(randfloat()*100).','.strval(randfloat()*100);
//echo strval(randfloat()*100).','.strval(randfloat()*100);
//echo '<br>';
fputs($file, $String);
fputs($file, "\r\n");
}

fclose($file);
}catch(PathException $e){
echo 'Exception';
}

?>

Para hacer una estimación de cuánto puede durar el proceso de creación de cada archivo se asume que 5000 lineas de fichero dura unos 2 minutos aproximadamente. Y como este script solo abre un fichero y escribe sobre una pila de instrucciones anteriores, podemos considerar que este proceso se ejecuta linealmente; por lo que se puede calcular que:

10 millones de lineas –> 4 minutos
20 millones de lineas –> 8 minutos –> 640 MB50 millones de lineas –> 20 minutos –> 1.52 GB
100 millones de lineas –> 40 minutos–>3,23 GB
500 millones de lineas –> 200 minutos (3h y 30 min). Aquí ya empieza a pesar la cosa.

Advertencia

Esta función no tiene efecto cuando PHP se ejecuta en modo seguro. No hay ninguna solución más que deshabilitar el modo seguro o cambiar el tiempo límite en el php.ini.

*Este archivo servirá para introducir datos dentro de una base de datos y contener millones de registros. Como se habló en un post anterior, crear rutinas para hacer esto mismo lleva muchísimo más tiempo, por lo que será mejor introducir registros por este método que por cualquier otro.