Comunidad de diseño web y desarrollo en internet online

REGEX VS Muchos IF y FOR

Citar            
MensajeEscrito el 02 Mar 2009 06:30 am
Motivado por la discusión de este tema y y por muchos artículos que hablan sobre el (mal) rendimiento de las REGEX, me decidí a hacer una prueba con un código que estoy haciendo...

El código maneja cadenas... La idea es hacer un sistema de plantillas pero algo complejas, como las de Smarty.

Básicamente en mi template tendría variables y funciones de plantilla, por ej:

Una variable sería: {variable_name}
La variable también podría tener modificador, {variable_name|modificador} nótese el "|" luego del nombre de la variable
Y las funciones serían algo como {function_name file="my_file" title="my title"} nótese que luego del nombre de la función va un espacio en blanco y luego la lista de parámetros...

Bien. Para no complicar el ejemplo voy solamente a dividir tanto las variables como las funciones en 2 partes: nombre y argumentos|modificadores... El código que voy a exponer simplemente debería extraer el nombre de la variable o de la funcion, validando que la misma sea correcta (no contenga caracteres inválidos, etc) y por otro lado va a extrar la otra parte sin procesarla ni validarla.

Para ello partiré de un punto ficticio donde tengo un array con todas las variables o funciones de mi plantilla sin delimitadores, es decir sin las llaves a los lados.

Ah, casi lo olvido... las variables pueden estar dividas en segmentos así: segmento1.segmento2.segmento3 (nótese los puntos ".") Y tanto funciones como variables o segmentos deben empezar con una letra, y tener sólo letras, números y guion bajo

Según mi pc y el método :oops: que usé para probar la velocidad, el código con regex es aprox. 40% más rápido... Espero que se animen a probar esto y quizá intentar otra solución más óptima ya sea con regex o sin ellas, a ver que tal :)

Bien... Aquí ambos códigos:

Sin REGEX

Código PHP :

<?php

$tiempo_inicio = microtime(true);

/***/

$strings = array
(
'contact.phone.home|truncate:30:"..."',
'include_tpl file="test" title="another test" test=1 var_test=contact.phone.home|truncate',
'contact.phone.home',
'cristalab',
'clab',
'love4clab',
'freddie',
'ramm',
'dano',
'maik',
'google',
'youtube',
'facebook',
'dessigual.com',
'word_with_09_numbers',
'word_with_underscore',
'simply',
'dummy',
'text',
'printing',
'typesetting',
'industry'
); 

foreach($strings as $string)
{

   $n =  strlen($string);
   
   $mustBeAlpha = true;
   $isVar = false;
   $name = '';
   
   $varName = '';
   $functionName = '';
   
   $i = 0;
   
   for(; $i < $n; $i ++)
   {
      $l = $string[$i];
      
      if($mustBeAlpha)
      {
         if(ctype_alpha($l))
         {
            $name .= $l;
            $mustBeAlpha = false;
         }
         else
         {
            die("Nombre de variable/funcion invalida: <strong>$string</strong>");
         }
      }
      else if(ctype_alnum($l) || ($l == '_'))
      {
         $name .= $l;
      }
      else if($l == '.')
      {
         $name .= $l;
         $isVar = true;
         $mustBeAlpha = true;
      }
      else if($l == '|')
      {
         $varName = $name;
         break;
      }
      else if($l == ' ')
      {
         if($isVar)
         {
            die("Nombre de variable/funcion invalida: <strong>$string</strong>");
         }
         
         $functionName = $name;
         
         break;
      }
      else
      {
         die("Nombre de variable/funcion invalida: <strong>$string</strong>");
      }
         
   }
   
   if($name[$i - 1] == '.')
   {
      die('Nombre de variable/funcion invalida');
   }
   
   if($i < $n)
   {      
      $arguments = substr($string, $i + 1);
   }
   else
   {
      $arguments = '';
   }
   
   if($functionName != '')
   {
      echo "Function name: $name --- ";
      echo "Arguments: $arguments";
   }
   else
   {
      echo "Varname: $name --- ";
      echo "Modifiers: $arguments";
   }
   
   echo "<br />\n";
   
}

/***/

$tiempo_final = microtime(true);
$tiempo = $tiempo_final - $tiempo_inicio;
echo "<br />\nTotal: $tiempo segundos\n";

?>


Con REGEX:

Código PHP :

<?php

$tiempo_inicio = microtime(true);

/***/

$strings = array
(
'contact.phone.home|truncate:30:"..."',
'include_tpl file="test" title="another test" test=1 var_test=contact.phone.home|truncate',
'contact.phone.home',
'cristalab',
'clab',
'love4clab',
'freddie',
'ramm',
'dano',
'maik',
'google',
'youtube',
'facebook',
'dessigual.com',
'word_with_09_numbers',
'word_with_underscore',
'simply',
'dummy',
'text',
'printing',
'typesetting',
'industry'
);

$namePattern = '[a-z][\w]+';
$varPattern = '/(' . $namePattern . ')(?:( .+)|(?:((?:\.' . $namePattern . ')*)(?:\|(.+))?))?/';

foreach($strings as $string)
{
   
   $functionName = '';
   $varName = '';

   /*
   Var Pattern:
   matches: 
      2 -> name,
      3 -> function arguments,
      4 -> another part of the name var
      5 -> var modifiers
   */
   if(preg_match($varPattern, $string, $matches))
   {
      if(empty($matches[2]))
      {
         $varName = $matches[1];
         
         if(isset($matches[3]))
         {
            $varName .= $matches[3];
         }

         if(isset($matches[4]))
         {
            $arguments = $matches[4];
         }
         else
         {
             $arguments = '';
         }
      }
      else
      {
         $functionName = $matches[1];
         $arguments = $matches[2];
      }
   }
   else
   {
      die('Nombre de variable/funcion invalida');
   }
   
   if($functionName != '')
   {
      echo "Function name: $functionName --- ";
      echo "Arguments: $arguments";
   }
   else
   {
      echo "Varname: $varName --- ";
      echo "Modifiers: $arguments";
   }
   
   echo "<br />\n";

}

/***/

$tiempo_final = microtime(true);
$tiempo = $tiempo_final - $tiempo_inicio;
echo "<br />\nTotal: $tiempo segundos\n";

?>

Por Duilio

Claber

2590 de clabLevel

25 tutoriales
1 articulo

Genero:Masculino   Premio_Secretos

Venezuela

firefox
Citar            
MensajeEscrito el 04 Mar 2009 09:47 pm
Regex para que reinventar la rueda mejor aprender regex te complicas menos la vida tratando de hacer algo que ya existe
;-D

Por talcual

686 de clabLevel



 

Colombia

firefox
Citar            
MensajeEscrito el 04 Mar 2009 10:35 pm
talcual no es que duilio no sepa regexp, porque sí lo sabe. El motivo de publicar esto es por los constantes comentarios que él (Duilio) ha escuchado de que regexp es lento.

Ahora si bien es cierto que regexp requiere mucho procesador, no quiere decir que no se deba usar y que sea muy lento. La cuestión Duilio es que cuando uno (me incluyo) aprende regexp se cree c00l y quiere hacer todo con expresiones regulares, cuando en verdad los metodos clasicos son suficientes y no requieren tanto procesamiento como con regexp.

Regexp se debe usar para analizar grandes cantidades de texto, pues por los métodos tradicionales sería muy lento aparte de tedioso. Existen sistemas de plantillas que no requieren el poder de expresiones regulares pero otras sí. No he probado tu codigo, pero en cuanto lo haga te digo mi opinión.

saludos

Por Maikel

BOFH

5575 de clabLevel

22 tutoriales
5 articulos

Genero:Masculino   Team Cristalab

Claber de baja indefinida

firefox
Citar            
MensajeEscrito el 05 Mar 2009 04:16 am
maikel hay si te doy la razon cuando se programa se debe usar las herramientas bien usadas con eso quiero decir que para que usar regex para unas 2 lineas no seria algo tedioso en cambio si tenemos un parrafo de 400 lineas hay seria conveniente llamar a nuestro amigo Regex saludos ese es mi punto de vista y creo q el de muchos

Por talcual

686 de clabLevel



 

Colombia

firefox
Citar            
MensajeEscrito el 05 Mar 2009 05:17 pm
Hola

Si pues te recomiendo 2 cosas.... primero comparar el tiempo de ejecucion de las 2 opciones, no solo en tu maquina, sino en un ambiente simulando un proceso real de uso de la aplicacion... o sea con miles de peticiones diferentes (fijate algun test de rendimiento)

Por otro lado, si estas usando para crear templates lo mejor es q cachees todo lo q puedas, con eso vas a tener una mejora global de rendimiento ya se la opcion q decidas utilizar.


Si bien el uso de expresiones regulares puede requerir mucho procesamiento, su utilizacion o no no debe depender de esa unica variable, por ejemplo, si a tu web entran solo 10 personas por mes, no te va a importar mucho el rendimiento, pero si es una red social obviamente q si. Por otro lado tambien q tipo de expresiones necesitas analizar, el mantenimiento del choclo de codigo de if y for en comparacion de 1 o 2 lineas de utilzar regex.... etc...


Saludos!

Por alfathenus

833 de clabLevel

5 tutoriales

 

buenos aires || Argentina

firefox

 

Cristalab BabyBlue v4 + V4 © 2011 Cristalab
Powered by ClabEngines v4, HTML5, love and ponies.