2008-10-03 10 views
5

Estoy ejecutando una expresión regular contra un escalar grande. Aunque este partido no es la captura de cualquier cosa, mi proceso crece por 30M después de este partido:¿Por qué mi Perl Regex usa tanta memoria?

# A 
if (${$c} =~ m/\G<<\s*/cgs) 
{ 
    #B 
    ... 
} 

$c es una referencia a una bastante grande escalar (alrededor de 21 millones), pero he comprobado que es pos(${$c}) en la derecha el lugar y la expresión coinciden en el primer carácter, con pos(${$c}) siendo actualizado al lugar correcto después de la coincidencia. Pero como mencioné, el proceso ha crecido en aproximadamente 30M entre #A y #B, a pesar de que no estoy capturando nada con este partido. ¿A dónde va mi memoria?

Editar: Sí, el uso de $& tenía la culpa. Estamos usando Perl 5.8.8, y mi script usaba Getopt::Declare, que usa el Text::Balanced incorporado. La versión 1.95 de este módulo estaba usando $&. La versión 2.0.0 que se incluye con Perl 5.10 ha eliminado la referencia a $& y alivia el problema.

Respuesta

20

Solo un rápido comentario de cordura, ¿mencionas $ &, $ `o $ '(a veces llamado $ MATCH, $ PREMATCH y $ POSTMATCH) en cualquier parte de tu código? Si es así, Perl copiará toda la cadena para cada coincidencia de expresión regular, en caso de que quiera inspeccionar esas variables.

"En su código" en este caso significa indirectamente, incluyendo el uso de módulos que hacen referencia a estas variables, o escribiendo use English en lugar de use English qw(-no_match_vars).

Si no está seguro, puede utilizar el módulo Devel::SawAmpersand para determinar si se han utilizado, y Devel::FindAmpersand averiguar donde se utilizan.

Puede haber otras razones para el aumento en la memoria (¿qué versión de Perl estás usando?), Pero las variables de coincidencia definitivamente te volarán la memoria si se usan, y por lo tanto, son un posible culpable.

Cheerio,

Paul

+0

Ciertamente parece que eso es todo. No puedo ejecutar FindAmpersand en mi Perl porque tengo hilos habilitados, por lo que recompilaré Perl solo para ejecutar esta prueba, pero SawAmpersand informa que sí. –

+0

grep o ack también deberían poder decirle si se mencionan en algún lugar de su código. –

+0

Intenté eso y no encontré nada en mi código, así que finalmente comencé a analizar todas las bibliotecas en @INC, y finalmente lo reduje a GetOpt :: Declare, que estaba usando $ &. Deshacerse de esa biblioteca fue un gran paso para solucionar mis problemas de uso de memoria. –

Cuestiones relacionadas