2012-01-20 13 views
6

Tengo en clase alrededor de 100 Regex llamadas, cada llamada cubre diferentes tipos de datos en el protocolo de texto, pero tengo muchos archivos y en función de los análisis regex tomó el 88% de la ejecución de mi código.Reemplazo más rápido para Regex

muchos este tipo de código:

{ 
    Match m_said = Regex.Match(line, @"(.*) said,", RegexOptions.IgnoreCase); 
    if (m_said.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 

{ 
    Match ma = Regex.Match(line, @"(.*) is connected", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 
{ 
    Match ma = Regex.Match(line, @"(.*): brings in for (.*)", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    long amount = Detect_Value(ma.Groups[2].Value, line); 
    // some action 
    return true; 
    } 
} 

alguna manera de reemplazar Regex con alguna otra solución más rápida?

+1

creo que depende del tipo de expresiones regulares que está utilizando ... proporcionar algunas muestras! –

Respuesta

8

Para expresiones regulares que se prueban en el bucle, es a menudo más rápido es precompilación ellos fuera del bucle y justo prueba ellos dentro del bucle.

Debe declarar las diferentes expresiones regulares primero con sus respectivos patrones y solo llamar al Match() con el texto para probar en un segundo paso.

+1

¿La clase RegEx no tiene un caché? –

+0

@HenkHolterman: De hecho. Acabo de verificar eso en el documento. (Estoy más acostumbrado a PCRE que no proporciona un mecanismo de caché). La caché debería funcionar para las llamadas estáticas 'Regex.Match()' realizadas por el OP. O hay demasiadas expresiones regulares involucradas y 'Regex.CacheSize' es un camino a explorar para mejorar el rendimiento (pero lo dudo). – Seki

+0

Gracias hombre trabaja 10 veces más rápido ;-)))) – Svisstack

1

Se podría tratar de compilar la expresión regular de antemano o considerar la combinación de todas las expresiones expresiones regulares individuales en un (monstruo) Regex:

Match m_said = Regex.Match(line, 
      @"(.*) (said|(is connected)|...|...),", 
      RegexOptions.IgnoreCase); 

entonces usted puede probar el segundo grupo de captura para determinar qué ocurrió tipo de partido.

+0

Esta es la única respuesta que veo que los intentos de escanear el archivo (s) sólo una vez. –

+0

Dependiendo de los posibles textos, puede haber un problema con el @ "dije (*.)" Versión alltogether: ¿Qué pasa si 'User17 dijo "Ya he dicho eso!"' - la expresión regular se encuentra el mal "dicho" –

+1

no puedo hacer eso, las líneas tienen diferentes formatos, por ejemplo, no X comando Y. – Svisstack

1

Sé expresión regular puede hacer muchas cosas, pero aquí es un punto de referencia con la expresión regular vs vs char.Split string.split

http://www.dotnetperls.com/split en la sección de los Puntos de Referencia

+1

Creo que el sitio acaba de violar mis ojos. – adelphus

+0

tienes razón al respecto -_- –

3

Aparte de precompilar su expresión regular, usted podría gane (probablemente mucho más) beneficios de rendimiento escribiendo una expresión regular más precisa. En este sentido, .* es casi siempre una mala elección:

(.*) is connected significa: Primero que coincida con la cadena de toda (esa es la parte .*), a continuación, dar marcha atrás un carácter a la vez hasta que sea posible para que coincida con is connected.

Ahora, a menos que la cuerda sea muy corta o is connected aparece muy cerca del final de la cuerda, eso implica un gran retroceso que lleva tiempo.

Así que si puede refinar la coincidencia permitida, puede mejorar el rendimiento.

Por ejemplo, si solo se permiten caracteres alfanuméricos, entonces (\w+) is connected será bueno. Si se trata de cualquier tipo de caracteres que no sean espacios en blanco, entonces use (\S+) is connected. Etc., dependiendo de las reglas para una coincidencia válida.

En su ejemplo concreto, no parece estar haciendo nada con la coincidencia capturada, por lo que incluso podría descartar la expresión regular por completo y solo buscar una subcadena fija. Cuál método será el más rápido al final depende mucho de su entrada y requisitos reales.

+0

Gah! Estaba a punto de escribir un comentario acerca de uno de los puntos fuertes de las expresiones regulares que pueden compilarse para DFA, sin necesidad de retroceder. Pero entonces miré a la documentación para la puesta en práctica de las expresiones regulares de .NET y [* tienes razón! *] (Http://msdn.microsoft.com/en-us/library/dsy130b4.aspx) –

2

No sé si puede volver a utilizar las expresiones, o si el método se llama varias veces, pero si es así, debe precompilar sus expresiones regulares. Prueba esto:

private static readonly Regex xmlRegex = new Regex("YOUR EXPRESSION", RegexOptions.Compiled); 

En su muestra, cada vez que se utiliza el método que 'recoge' la expresión, pero esto es innnecesario como la expresión es una constante.Ahora está precompilado, compilado solo una vez. La desventaja es que la primera vez que accede a la expresión, es un poco más lento.

+1

gracias ;-) esta es una buena respuesta con estos campos estáticos – Svisstack