2010-10-12 17 views
9

Sto cercando di analizzare un file XML di grandi dimensioni. L'ho letto utilizzando XML :: SAX (utilizzando Expat, non l'implementazione Perl) e mettere tutto il secondo livello e al di sotto nodi nel mio "nodo" di classe:Perché il codice Moose è così 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; 

Nel sottomenu "end_element", verifico se questo è un nodo che mi interessa, e se lo è, faccio qualche ulteriore elaborazione.

Questo ha funzionato correttamente sui miei file di test, ma l'altro ieri l'ho lanciato sul mio file reale, tutti i 13 milioni di righe di esso, e richiede sempre. Funziona da oltre 36 ore. Come faccio a sapere se è Moose o XML :: SAX che è il collo di bottiglia? Moose è sempre lento, o lo sto usando male?

Aggiornamento Facendo un profilo su una linea di 20.000 sottoinsieme dei dati mostra che si tratta di Moose che è il collo di bottiglia - in particolare nella classe :: :: MOP Class :: compute_all_applicable_attributes (13,9%) e altri di classe e le classi Moose.

+2

L'alce può sembrare lento, ma non farlo arrabbiare ... –

+8

'Classe :: MOP :: Class :: compute_all_applicable_attributes' è qualcosa che deve essere fatto molto se non si' __PACKAGE __-> meta -> make_immutable' le tue lezioni come ho suggerito nella mia risposta. Come cambia il profilo se lo fai? – rafl

+1

@Ether, quello riguardava il costo di avvio. Il mio riguarda i costi di gestione, in particolare la creazione e distruzione di oggetti. –

risposta

22

Mentre Moose fa un po 'di lavoro all'avvio, che a volte lo fa apparire un po' lento, il codice che genera, specialmente cose come gli accessors per gli attributi, sono generalmente un po 'più veloci di quello che il programmatore medio perl sarebbe in grado scrivere. Quindi dato il tempo di esecuzione del tuo processo è piuttosto lungo, dubito che qualsiasi overhead indotto da Moose sarà rilevante.

Tuttavia, dal codice che hai mostrato, non riesco davvero a capire quale sia il tuo collo di bottiglia, anche se credo fermamente che non sia Moose. Voglio anche sottolineare che fare __PACKAGE__->meta->make_immutable, per affermare che la tua classe è ora "finalizzata", consente a Moose di fare ulteriori ottimizzazioni, ma dubito comunque che ciò ti stia causando problemi.

Che ne dici di prendere un campione più piccolo dei tuoi dati, così il tuo programma finirà in un tempo ragionevole, e dare un'occhiata a quello in un profiler come Devel::NYTProf. Sarà in grado di dirti dove viene speso esattamente il tempo nel tuo programma, in modo da poter ottimizzare specificamente quelle parti per ottenere il massimo guadagno possibile.

Una possibilità è che i vincoli di tipo si stanno utilizzando un po 'di cose lente. Realmente convalidare gli attributi di istanza in modo approfondito su ogni singolo accesso di scrittura a loro (o sull'istanza della classe), non è qualcosa che la maggior parte dei programmatori farebbe di solito. Potresti provare a utilizzare vincoli più semplici, ad esempio ArrayRef anziché ArrayRef[Node], se sei abbastanza sicuro sulla validità dei tuoi dati. In questo modo, verrà controllato solo il tipo del valore dell'attributo stesso, non il valore di ogni elemento in quel riferimento di matrice.

Ma ancora, profila il tuo codice. Non indovinare

+3

+1 Per il suggerimento di profilazione –

+0

NYTProf è molto meglio di DProf? –

+10

No, molto più di questo. – rafl

2

Ho scritto con successo applicazioni di elaborazione XML di grandi dimensioni utilizzando il file XML::Twig 745mb impiegare meno di un'ora per l'esecuzione su una scatola di dimensioni ragionevoli.

Ma come altri utenti hanno già menzionato, è necessario profilare il codice per capire che cosa sta causando esattamente il problema.

6

Ho il forte sospetto che il problema di velocità non sia in Moose tanto quanto lo è nell'allocazione della memoria e nello scambio del disco. Anche senza fare -> meta-> make_immutable, in base ai tuoi tempi per il sottoinsieme 20K, lo script dovrebbe terminare in circa 2 ore (((11 * (13_000_000/20_000))/60) == ~ 119 min). Facendo -> meta-> make_immutable lo avrebbe ridotto a ca. 65 minuti circa.

Prova a eseguire nuovamente il tuo script grande e vedere cosa stanno facendo la tua memoria e lo scambio, ho il sospetto che tu dia il tuo disco un tremendo battito.

+0

Munin dice che stavo quasi scambiando durante le prime 36 ore di funzionamento. Vedi http://xcski.com/munin/xcski.com/allhats2.xcski.com-cpu.html, http://xcski.com/munin/xcski.com/allhats2.xcski.com-memory.html e http : //xcski.com/munin/xcski.com/allhats2.xcski.com-swap.html dalla sera del 10 ottobre a metà mattina del 12 ottobre. Puoi vedere più swap in uso durante la seconda esecuzione (a partire dalle 10 di mattina su 12Oct) dopo che ho fatto make_immutable, ma ciò potrebbe essere correlato ad altre cose che stavo facendo allo stesso tempo. –

+7

Invisito per essere Stevan Little. – jrockway

Problemi correlati