2010-04-27 18 views
8

Ich habe eine Hands-on rekursive reine Python-Parser für ein bestimmtes Dateiformat (ARFF) geschrieben, die wir in einer Vorlesung verwenden. Jetzt läuft meine Übungseingabe furchtbar langsam. Es stellt sich heraus, dass die meiste Zeit in meinem Parser verbracht wird. Es kostet viel CPU-Zeit, die HD ist nicht der Flaschenhals.schreibe einen schnellen Parser in Python

Ich frage mich, welche performanten Möglichkeiten gibt es einen Parser in Python zu schreiben? Ich würde es lieber nicht in C umschreiben. Ich habe versucht, jython zu benutzen, aber das hat die Performance stark reduziert! Die Dateien, die ich analysiere, sind teilweise sehr groß (> 150 MB) mit sehr langen Zeilen.

Mein aktueller Parser benötigt nur eine Vorausschau auf ein Zeichen. Ich würde die Quelle hier posten, aber ich weiß nicht, ob das eine so gute Idee ist. Nach all dem ist die Abgabefrist noch nicht beendet. Der Fokus in dieser Übung liegt jedoch nicht auf dem Parser. Sie können wählen, welche Sprache Sie verwenden möchten, und es gibt bereits einen Parser für Java.

Hinweis: Ich habe ein x86_64 System so Psyco (und es scheint auch PyPy) ist keine Option.

Update: Ich habe jetzt meinen Parser/Writer auf bitbucket hochgeladen.

+4

Haben Sie Ihren Parser profiliert? Wahrscheinlich ist es nur ein Engpass, der alles aufhält. –

+0

Ohne ein Codebeispiel ist es unmöglich, anständige Ratschläge zu geben. Sie könnten eine solide Technik mit einem großen Fehler verwenden, oder Ihr gesamter Ansatz muss möglicherweise überarbeitet werden, wir haben keine Möglichkeit zu wissen. – mikerobi

+0

Haben Sie versucht, mit Psyco damit? –

Antwort

8

Sie könnten oder pyparsing verwenden, sie könnten Ihren Analyseprozess beschleunigen.

Und wenn Sie Ihren aktuellen Code behalten möchten, können Sie sich Cython/PyPy ansehen, was Ihre Leistung erhöht (manchmal bis zu 4x).

+1

Unwahrscheinlich, dass Pyapsing die Dinge beschleunigen wird, könnte aber einige Einblicke geben, wo die Engpässe sind. Ich glaube auch, dass ein ARFF-Pyparsing-Parser bereits geschrieben wurde und irgendwo im Äther ist. – PaulMcG

+0

Das stimmt - und ich weiß nicht, wie Pyaps mit PyPy oder Cython passt. – wvd

+0

Der von der Weka-Site verlinkte ARPF-Parsing-Parser ist äußerst unvollständig (wenn Sie von diesem Wort sprechen). Auch ich habe versucht, Cython, aber weil ich Ausbeute verwenden, musste ich eine HG-Version verwenden und alles, was tat, ist Code, der segfaults produzieren. – panzi

7

Der allgemeinste Tipp, den ich ohne weitere Informationen geben würde, wäre, die gesamte Datei oder zumindest einen wesentlichen Teil davon sofort in den Speicher zu schreiben. Du willst es nicht Charakter für Buchstabe lesen und hier und da suchen; Unabhängig von der Pufferung, die unter der Haube abläuft, ist es wahrscheinlich eine gute Idee, das Ganze im Speicher zu haben, damit man es wie gewünscht bedienen kann.

Ich habe Parser in Python geschrieben und es gibt keine besondere Voraussetzung dafür, dass sie besonders langsam sind als ein Parser in einer anderen Sprache. Wie bei solchen Dingen ist es wahrscheinlicher, dass du Arbeit machst, die du nicht tun musst. Von diesen Objektklassen ist das Erstellen und Zerstören und Wiederherstellen desselben Objekts teurer als das bloße Ablegen. Einen Wert immer und immer wieder neu zu berechnen ist teurer als nur irgendwo zu speichern. Usw.

In Python ist eine Falle, in die Leute hineinfallen, eine Menge unnötiger Stringmanipulationen. Hängen Sie Zeichenfolgen nicht an Zeichenfolgen an. Wenn Sie Ihre Token aufbauen, arbeiten Sie an der "Master" -String und entfernen Sie den Token auf einen Schlag. (Mit anderen Worten, indexieren Sie in die "Master" -Zeichenfolge, ermitteln Sie die Anfangs- und Endpunkte, und fassen Sie sie dann mit token = master[start:end].) Zeichenketten hintereinander auszuführen ist ein kurzer Weg zum Performance-Elend. Ich vermute, auch wenn Sie wollen/müssen aus irgendeinem Grund zu tun for c in master: newstr += c haben Sie möglicherweise mehr Glück stopfen die 'cs in eine Liste und dann newstr = ''.join(newstr_charlist).

+0

Ich benutze solche Dinge oft, ist das der schnellste Weg? Dieser spezielle Code wird jedoch nicht von mir Anwendungsfällen ausgelöst. http://pastebin.com/yAmEcKB8 – panzi

+0

Oh, und ich lese 4096 Byte Chunks aus der Datei (die readc() und peek() -Methode funktionieren auf diese Chunks). Ich glaube nicht, dass das Lesen der Hole-Datei eine gute Idee wäre, da die Dateien> 150 MB groß sind. – panzi

+2

Moderne Computer haben 512M oder mehr Speicher. 150MB lesen ist nichts. :) –