2010-04-27 11 views
8

Ho scritto un hands-on ricorsiva parser pitone puro per un formato di qualche file (ARFF) usiamo in una lezione. Ora la mia presentazione di esercizio è terribilmente lenta. Risulta di gran lunga il tempo più speso nel mio parser. Sta consumando molto tempo CPU, l'HD non è il collo di bottiglia.scrivere un parser veloce in python

Mi chiedo quali modi performanti ci sono per scrivere un parser in python? Preferirei non riscriverlo in C. Ho cercato di usare jython, ma ho ridotto molto le prestazioni! I file che analizzo sono in parte enormi (> 150 MB) con linee molto lunghe.

Il mio parser corrente ha bisogno solo di un look-ahead di un carattere. Pubblicherei la fonte qui, ma non so se sia una buona idea. Dopo tutto il termine di presentazione non è ancora finito. Ma poi, l'attenzione in questo esercizio non è il parser. Puoi scegliere qualsiasi lingua tu voglia usare e c'è già un parser per Java.

Nota: ho un sistema x86_64 così psyco (e sembra anche PyPy) non è un'opzione.

Aggiornamento: ora caricato il mio parser/scrittore di bitbucket.

+4

Hai profilato il parser? È probabile che sia solo un collo di bottiglia a trattenere tutto. –

+0

Senza un esempio di codice è impossibile dare un consiglio decente. Potresti usare una tecnica sonora con un difetto importante, o il tuo intero approccio potrebbe dover essere rielaborato, non abbiamo modo di saperlo. – mikerobi

+0

Hai provato a usare psyco con esso? –

risposta

8

È possibile utilizzare ANTLR o pyparsing, potrebbero accelerare il processo di analisi.

E se si desidera mantenere il vostro codice attuale, si potrebbe desiderare di guardare Cython/PyPy, che aumenta la tua perfomance (a volte fino a 4x).

+1

Improbabile che il pyparsing acceleri le cose, ma potrebbe fornire alcune informazioni su dove sono i colli di bottiglia. Inoltre, credo che un parser ARyp pyparsing sia già stato scritto, ed è fuori nell'etere da qualche parte. – PaulMcG

+0

Questo è vero - e non so come il pyparsing si adatti a PyPy o Cython. – wvd

+0

Il parser di pypars dell'ARFF collegato dal sito weka è estremamente incompleto (se è quello di cui si sta parlando). Inoltre ho provato cython, ma poiché uso molto rendimento ho dovuto usare una versione hg e tutto ciò che è stato prodotto è stato il codice che segfaults. – panzi

7

La punta più generale darei senza ulteriori informazioni sarebbe quello di leggere l'intero file, o almeno una parte sostanziale di esso, in memoria in una sola volta. Non vuoi leggerlo un personaggio alla volta e cercare qua e là; indipendentemente dal buffering che sta succedendo sotto il cofano, probabilmente è una buona idea avere l'intera cosa in memoria in modo da poter operare su di esso come si desidera.

ho scritto parser in Python e non c'è alcun requisito particolare per loro di essere particolarmente lento di un parser scritto in qualsiasi altra lingua. Come succede con questo genere di cose, è più probabile che tu stia facendo un lavoro che non devi fare. Di quelle classi di oggetti, creare, distruggere e ricreare lo stesso oggetto è più costoso che archiviarlo da qualche parte. Ricalcolare un valore più e più volte è più costoso che archiviarlo da qualche parte. Ecc, ecc

In Python specificamente, una trappola che persone cadono in sta facendo un sacco di manipolazione delle stringhe inutili. Non aggiungere alle stringhe un carattere alla volta; quando costruisci le tue pedine fai il tuo lavoro sulla corda "principale" e spoglia la pedina in un colpo solo. (In altre parole, indicizza la stringa "principale", individua i punti iniziale e finale, quindi prendi lo token = master[start:end]). Fare concatenazione di stringhe un carattere alla volta è un breve percorso verso la miseria delle prestazioni. Sospetto anche se tu voglia/abbia bisogno di fare qualche ragione per fare for c in master: newstr += c potresti avere più fortuna a riempire la 'c's in una lista e poi a newstr = ''.join(newstr_charlist).

+0

Uso spesso cose del genere, è questo il modo più veloce? Tuttavia, questo particolare codice non viene attivato dai casi di utilizzo. http://pastebin.com/yAmEcKB8 – panzi

+0

Oh e ho letto blocchi di 4096 byte dal file (il metodo readc() e peek() operano su questi blocchi). Non penso che leggere il file del foro sarebbe una buona idea perché i file arrivano fino a> 150 MB di dimensione. – panzi

+2

I computer moderni hanno 512 M o più di memoria. Leggere 150 MB non è niente. :) –