Rendimiento

Ciertos elementos que pueden aparecer en patrones son más eficientes que otros. Es más eficiente usar una clase de caracteres como [aeiou] que un conjunto de alternativas como (a|e|i|o|u). En general, la construcción más simple que proporciona el comportamiento requerido suele ser la más eficiente. El libro de Jeffrey Friedl contiene mucha discusión sobre cómo optimizar expresiones regulares para un rendimiento eficiente.

Cuando un patrón comienza con .* y la opción PCRE_DOTALL está establecida, el patrón está implícitamente anclado por PCRE, ya que solo puede coincidir al inicio de una cadena de sujeto. Sin embargo, si PCRE_DOTALL no está establecida, PCRE no puede hacer esta optimización, porque el metacarácter . no coincide entonces con un salto de línea, y si la cadena de sujeto contiene saltos de línea, el patrón puede coincidir desde el carácter inmediatamente después de uno de ellos en lugar de desde el principio. Por ejemplo, el patrón (.*) second coincide con la cadena de sujeto "first\nand second" (donde \n representa un carácter de nueva línea) con la primera subcadena capturada siendo "and". Para hacer esto, PCRE tiene que volver a intentar la coincidencia comenzando después de cada salto de línea en el sujeto.

Si está utilizando un patrón como este con cadenas de sujeto que no contienen saltos de línea, el mejor rendimiento se obtiene estableciendo PCRE_DOTALL, o comenzando el patrón con ^.* para indicar anclaje explícito. Esto ahorra a PCRE tener que escanear a lo largo del sujeto buscando un salto de línea para reiniciar.

Tenga cuidado con los patrones que contienen repeticiones indefinidas anidadas. Estos pueden tardar mucho tiempo en ejecutarse cuando se aplican a una cadena que no coincide. Considere el fragmento de patrón (a+)*

Esto puede coincidir con "aaaa" de 33 maneras diferentes, y este número aumenta muy rápidamente a medida que la cadena se alarga. (La repetición * puede coincidir 0, 1, 2, 3 o 4 veces, y para cada uno de esos casos excepto 0, las repeticiones + pueden coincidir con diferentes números de veces.) Cuando el resto del patrón es tal que toda la coincidencia va a fallar, PCRE en principio tiene que probar cada variación posible, y esto puede tomar un tiempo extremadamente largo.

Una optimización atrapa algunos de los casos más simples como (a+)*b donde un carácter literal sigue. Antes de embarcarse en el procedimiento de coincidencia estándar, PCRE verifica que hay una "b" más adelante en el sujeto, y si no la hay, falla la coincidencia inmediatamente. Sin embargo, cuando no hay un carácter literal siguiente, esta optimización no puede usarse. Puede ver la diferencia comparando el comportamiento de (a+)*\d con el patrón anterior. El primero da un fallo casi instantáneamente cuando se aplica a una línea completa de caracteres "a", mientras que el segundo tarda un tiempo apreciable con cadenas más largas que unas 20 caracteres.