2009-09-29 9 views
5

Tengo una situación donde mis expresiones regulares se compilan muy lentamente en Windows Server 2008. Escribí una pequeña aplicación de consola para resaltar este problema. La aplicación genera su propia entrada y crea una Regex a partir de palabras en un archivo XML. Creé una versión de lanzamiento de esta aplicación y la ejecuté tanto en mi computadora portátil personal (que ejecuta XP) como en el servidor de Windows 2008. La expresión regular tomó 0,21 segundos para compilarse en mi computadora portátil, pero 23 segundos para compilar en el servidor.Regex lento en Windows Server 2008

¿Alguna idea de lo que podría estar causando esto? El problema es solo en el primer uso de Regex (cuando se compila por primera vez, luego está bien)

También encontré otro problema: al usar \s+ en la expresión regular en el mismo servidor de Windows 2008, los globos de memoria (usa 4GB +) y la compilación de Regex nunca termina.

¿Existe algún problema con Regex y 64 bit de .net? ¿Hay una solución/parche disponible para esto? Realmente no puedo encontrar ninguna información en la red, pero he encontrado algunos artículos sobre estos mismos problemas en Framework 2.0. ¿Seguro que ya se ha solucionado?

Más información: El servidor ejecuta la versión de 64 bit de .NET Framework (3.5 SP1) y en mi computadora portátil tengo instalados Visual Studio 2008 y el framework 3.5. La expresión regular es del siguiente patrón: ^word$|^word$|^word$ y está construido con las siguientes banderas: RegexOptions.IgnoreCase | RegexOptions.Compiled


Aquí es un fragmento de código:

StringBuilder regexString = new StringBuilder(); 
if (!String.IsNullOrEmpty(fileLocation)) 
{ 
    XmlTextReader textReader = new XmlTextReader(fileLocation); 
    textReader.Read(); 
    while (textReader.Read()) 
    { 
     textReader.MoveToElement(); 
     if (textReader.Name == "word") 
     { 
      regexString.Append("^" + textReader.GetAttribute(0) + "$|"); 
     } 
    } 
    ProfanityFilter = new Regex(regexString.ToString(0, regexString.Length - 1), RegexOptions.IgnoreCase | RegexOptions.Compiled); 
} 

DateTime time = DateTime.Now; 
Console.WriteLine("\nIsProfane:\n" + ProfanityFilter.IsMatch("test")); 
Console.WriteLine("\nTime: " + (DateTime.Now - time).TotalSeconds); 
Console.ReadKey(); 

Esto se traduce en un tiempo de 0,21 segundos en mi portátil y 23 segundos en el servidor 2008. El archivo XML consta de 168 palabras en el siguiente formato:

<word text="test" /> 
+3

¿Qué tal código de muestra, para expresiones regulares y xml? –

Respuesta

4

Encontré una solución, dada la correcta, pero perfecta en mi caso. Por alguna razón, si omito la bandera RegexOptions.Compiled, el Regex es mucho, mucho más rápido. Incluso logré ejecutar el Regex en 100 frases largas en menos de 65 milisegundos en el servidor de 2008.

Esto debe ser un error en .net lib, ya que se supone que la versión no compilada es mucho más lenta que la versión compilada. De cualquier manera, menos de 1 milisegundo por cheque es muy aceptable para mí :)

+0

Quizás también quiera experimentar con más patrones regex alternativos para encontrar el óptimo, como/^ (palabra | palabra | palabra | palabra) $/en lugar de/^ palabra $ |^palabra $ |^palabra $ /. – brianary

+0

Sí, soy consciente de eso. Como mencioné en la pregunta original, escribí una aplicación de consola simplemente para resaltar el problema. Esa misma Regex misma compila en 0,21 segundos en mi computadora portátil, por lo que no debería necesitar compilar durante 23 segundos en un servidor de 64 bits. – pjmyburg

+0

Tenía el mismo problema y la misma solución, con el que estaba listo para compilarse funcionaba bien en mi cuadro XP local, cuando subía al servidor tardaba más de 40 segundos por regex. Se eliminó la opción compilada y 8 llamadas ahora tardan menos de 1 segundo en total. – ManiacZX

4

Usted puede pre-compilar sus expresiones regulares usando el método Regex.CompileToAssembly, y luego se podría desplegar las expresiones regulares compiladas a su servidor.

+0

Sí, pero eso significa que los administradores no técnicos del servicio no pueden simplemente agregar una palabra a un archivo XML; las DLL tendrían que volver a compilarse cada vez. Buena sugerencia, sin embargo. – pjmyburg

+1

Creo que quiso decir que después de leer en el archivo, usa la opción RegexOptions.Compiled para optimizar la ejecución de la expresión regular. – brianary

+0

No, quiso decir que precompila Regex a un archivo DLL (ensamblado); eso es lo que hace el método CompileToAssembly. El indicador RegexOptions.Compiled es la causa de todo este problema. Esa es de hecho la forma en que me gustaría ir, pero parece que hay un error en las bibliotecas .net de 64 bits. – pjmyburg

1

Me encontré con exactamente el mismo problema. Mi aplicación funciona bien en máquinas x86 pero con globos de memoria y se cuelga en x64. Quitar la bandera de compilación no ayudó. Intenté esto hoy en .net 4.0 y el problema persiste. Si tiene una repro, le sugiero que presente un error.

creo MSFT sabe de esto, ver el fondo comment here

Pero dejarlos decidir si este es el mismo fallo. Agregue un enlace a su archivo aquí si lo hace para poder agregarle mis comentarios.

+0

Me encontré con el mismo problema con la aplicación .NET 4.0 que se ejecuta en Windows Server 2008 r2 máquina de 64 bits. ¿Alguna noticia sobre el tema? Doron – DoronBM

+0

@DoronBM, comente en el enlace de la base de datos de errores de Microsoft anterior y trabaje para escalarlo con su representante de Microsoft. ¡Gracias! Hasta donde sé, no ha habido una resolución. – Barka

Cuestiones relacionadas