2010-10-12 20 views
9

Estoy tratando de analizar un gran archivo XML. Lo leí el uso de XML :: SAX (usando expatriados, no la implementación del Perl) y poner todo el segundo nivel y por debajo de los nodos en mi clase "nodo":¿Por qué el código de Moose es tan lento?

package Node; 
use Moose; 

has "name" => 
(
    isa => "Str", 
    reader => 'getName' 
); 

has "text" => 
( 
    is => "rw", 
    isa => "Str" 
); 

has "attrs" => 
(
    is => "rw", 
    isa => "HashRef[Str]" 

); 

has "subNodes" => 
(
    is => "rw", 
    isa => "ArrayRef[Node]", 
    default => sub { [] } 
); 

sub subNode 
{ 
    my ($self, $name) = @_; 
    my $subNodeRef = $self->subNodes; 
    my @matchingSubnodes = grep { $_->getName eq $name } @$subNodeRef; 

    if (scalar(@matchingSubnodes) == 1) 
    { 

    return $matchingSubnodes[0]; 
    } 
    return undef; 
} 


1; 

En el "end_element" sub, puedo comprobar si este es un nodo que me importa, y si lo es, hago un procesamiento adicional.

Todo funcionó bien en mis archivos de prueba, pero anteayer lo tiré en mi archivo real, los 13 millones de líneas de este, y me está tomando una eternidad. Ha estado funcionando por más de 36 horas. ¿Cómo puedo saber si es Moose o XML :: SAX el cuello de botella? ¿Moose siempre es tan lento o lo estoy usando mal?

actualización Hacer un perfil en un subconjunto 20000 línea de los datos muestra que se trata de alces que es el cuello de botella - específicamente en la clase :: MOP :: :: Clase compute_all_applicable_attributes (13,9%) y otra clase y las clases de los alces.

+2

Moose puede parecer lento, pero no lo enoje ... –

+8

'Class :: MOP :: Class :: compute_all_applicable_attributes' es algo que debe hacerse mucho si no lo hace' __PACKAGE __-> meta -> make_immutable' tus clases como sugerí en mi respuesta. ¿Cómo cambia el perfil si haces eso? – rafl

+1

@Ether, ese fue sobre el costo de la puesta en marcha. El mío es sobre el costo de ejecución, especialmente la creación y destrucción de objetos. –

Respuesta

22

Mientras Moose hace bastante trabajo en el momento del inicio, lo que algunas veces hace que parezca un poco lento, el código que genera, especialmente elementos de acceso para atributos, es bastante más rápido que el programador de perl promedio. escribir. Dado que el tiempo de ejecución de su proceso es bastante largo, dudo que cualquier sobrecarga inducida por Moose sea relevante.

Sin embargo, desde el código que ha mostrado, realmente no puedo decir qué es el cuello de botella, aunque creo firmemente que no es Moose. También quiero señalar que al hacer __PACKAGE__->meta->make_immutable, afirmar que su clase está ahora "finalizada" le permite a Moose hacer más optimizaciones, pero aun así dudo que esto sea lo que le esté causando problemas.

¿Qué tal si toma una muestra más pequeña de sus datos, por lo que su programa terminará en un tiempo razonable, y eche un vistazo a eso en un generador de perfiles como Devel::NYTProf. Eso podrá decirle exactamente dónde se gasta el tiempo de su programa, de modo que pueda optimizar específicamente esas partes para obtener la mayor ganancia posible.

Una posibilidad es que las restricciones de tipo que está utilizando disminuyen bastante las cosas. En realidad, la validación de los atributos de las instancias tan exhaustivamente en cada acceso de escritura a ellos (o en la instanciación de clase) no es algo que la mayoría de los programadores usualmente hacen. Podría intentar usar restricciones más simples, como ArrayRef en lugar de ArrayRef[Node], si está seguro de la validez de sus datos. De esta forma, solo se controlará el tipo de valor del atributo en sí mismo, no el valor de cada elemento en esa referencia de matriz.

Pero aún así, perfila tu código. No adivine

+3

+1 Para la sugerencia de perfiles –

+0

¿Es NYTProf mucho mejor que DProf? –

+10

No, mucho más que eso. – rafl

2

He escrito con éxito grandes aplicaciones de procesamiento XML usando XML::Twig El archivo de 745mb tarda menos de una hora en ejecutarse en una caja de tamaño razonable.

Pero como otros usuarios ya lo han mencionado, necesita crear un perfil de su código para descubrir exactamente qué está causando el problema.

6

Sospecho que su problema de velocidad no está tanto en Moose como en la asignación de memoria y el intercambio de disco. Incluso sin hacer -> meta-> make_immutable, basado en sus tiempos para el subconjunto de 20K, su script debería terminar en aproximadamente 2 horas (((11 * (13_000_000/20_000))/60) == ~ 119 min. Al hacer -> meta-> make_immutable lo habría reducido a aprox. 65 minutos o menos.

Trate de ejecutar de nuevo su script grande y vea lo que están haciendo su memoria y swap, sospecho que le está dando a su disco una terrible paliza.

+0

Munin dice que apenas estaba intercambiando nada durante las primeras 36 horas de funcionamiento. Consulte http://xcski.com/munin/xcski.com/allhats2.xcski.com-cpu.html, http://xcski.com/munin/xcski.com/allhats2.xcski.com-memory.html y http : //xcski.com/munin/xcski.com/allhats2.xcski.com-swap.html desde la tarde de 10Oct hasta la media mañana de 12Oct. Puede ver más intercambio en uso durante la segunda ejecución (comenzando aproximadamente a las 10 am en 12Oct) después de que hice make_immutable, pero eso puede estar relacionado con otras cosas que estaba haciendo al mismo tiempo. –

+7

Votado por ser Stevan Little. – jrockway

Cuestiones relacionadas