2012-01-29 12 views
6

Tenemos un servicio de Windows creado en .Net 4.0, los servicios analizan archivos de texto grandes que están formados por líneas de valores separados por comas (varios millones de líneas, con entre 5 y 10 valores), no hay problema aquí, podemos leer las líneas, dividirlas en una colección de clave/valor y procesar los valores. Para validar los valores, usamos el paralelismo de datos para pasar los valores, que básicamente son una matriz de valores en formatos específicos, a un método que realiza la validación de RegEx en valores individuales.Uso de memoria y problemas conocidos con RegEx y diferentes versiones de Framework

Hasta ahora hemos utilizado expresiones regulares estáticas, no el método estático RegEx.IsMatch pero una propiedad de RegEx estática con RegexOption definido como RegexOptions.Compiled, como se detalla a continuación.

private static Regex clientIdentityRegEx = new Regex("^[0-9]{4,9}$", RegexOptions.Compiled); 

Usando este método, tuvimos una huella de memoria bastante estándar, la memoria aumentó marginalmente con el mayor número de valores en cada línea, el tiempo tomado era más o menos lineal con el número total de líneas.

Para permitir que la Expresión regular se use en otros proyectos, con versiones variables de Framework, hemos trasladado recientemente las propiedades de RegEx estáticas a un proyecto de utilidades comunes que ahora se compila utilizando .NET 2.0 CLR (las Expresiones regulares reales no tienen cambiado), el número de propiedades de RegEx expuestas ha aumentado a aproximadamente 60, de 25 aproximadamente. Desde que hicimos esto, comenzamos a tener problemas de memoria, un aumento en la memoria de 3 o más veces que en el proyecto original. Cuando perfilamos el servicio en ejecución, podemos ver que la memoria parece estar "goteando" de RegEx.IsMatch, no de un RegEx específico, sino de varios según el nombre.

Encontré el siguiente comentario en un antiguo MSDN blog post de uno de los equipos de BCL relacionados con .Net 1.0/1.1 RegEx.

Sin embargo, hay aún más costos de compilación que deberían mencionarse. Emitir IL con Reflection. Emite carga mucho código y usa mucha memoria, y esa no es la memoria que siempre recuperarás. En adición. en v1.0 y v1.1, nunca podríamos liberar el IL que generamos, lo que significa que se ha filtrado la memoria al usar este modo. Hemos solucionado ese problema en Whidbey. Pero la conclusión es que solo debe usar este modo para un conjunto finito de expresiones que sepa que se usarán repetidamente.

Agregaré que tenemos un perfil de "la mayoría" de las llamadas RegEx comunes y no puede replicar el problema individualmente.

¿Es este un problema conocido con .Net 2.0 CLR?

En el artículo son los escritores Unidos "Pero la conclusión es que sólo se debe utilizar este modo para un conjunto finito de expresiones que sabemos que será utilizado en varias ocasiones", lo que es probable que sea lo finito número de expresiones utilizadas de esta manera, y ¿es probable que esto sea una causa?

actualización : En línea con respuesta de @Henk Holterman ¿Hay alguna mejores prácticas de referencia probar expresiones regulares, específicamente RegEx.IsMatch, excepto el uso de la fuerza bruta de formato de volumen y el parámetro?

Respuesta: Hanks respuesta de "El escenario requiere un número limitado, fijo de objetos RegEx" era más o menos acertadas, que añaden los RegEx'es estáticas a la clase hasta que se aislaron las expresiones con un aumento notible en el uso de la memoria, estos se migraron a clases estáticas separadas que parecen haber resuelto algunos de los problemas de memoria.

Parece que, aunque no puedo conciliar esto, existe una diferencia entre el uso de RegEx compilado entre .NET 2.0 CLR y .NET 4.0 CLR ya que los problemas de memoria no ocurren cuando se cumplen únicamente para el marco de .NET 4.0 . (¿Alguna confirmación?)

+1

Bien, usted restucturó su código _y_ aumentó considerablemente el número de RegEx. ¿Puedes regresar y hacer uno a la vez? –

+0

¿Qué le dice exactamente el perfilador? Acerca del tipo de pérdida de memoria? –

+0

Sí, lo hemos hecho hoy tarde y con el proyecto compilado para .Net 2.0 CLR fue obtener un aumento en la memoria con exactamente el mismo número de RegEx utilizados anteriormente, parece que no hay relación directa con la cantidad que agregamos, pero cómo son llamados y el tipo de expresión. – Lloyd

Respuesta

1

El escenario requiere un número limitado y fijo de objetos RegEx. Eso no debería tener fugas. Debe verificar que en la nueva situación, los objetos RegEx aún se estén reutilizando.

La otra posibilidad es el aumento del número (60 de 25) expresiones. ¿Podría ser que solo uno de ellos sea un poco más complejo y lleve a un retroceso excesivo?

Cuestiones relacionadas