2015-07-16 8 views
8

Ich versuche, ant ANTLR3 grammar in eine ANTLR4 grammar zu konvertieren, um es mit der Antlr4-Python2-Laufzeit zu verwenden. Diese Grammatik ist ein C/C++ - Fuzzy-Parser.Slow ANTLR4 generiert Parser in Python, aber schnell in Java

Nachdem Umwandlung (im Grunde das Entfernen Baum Operatoren und semantische/syntaktische Prädikate), erzeugt ich die Python2 Dateien mit:

java -jar antlr4.5-complete.jar -Dlanguage=Python2 CPPGrammar.g4

Und der Code ohne Fehler erzeugt wird, so dass ich importieren es in meinem Python-Projekt (ich benutze PyCharm), um einige Tests zu machen:

import sys, time 
from antlr4 import * 
from parser.CPPGrammarLexer import CPPGrammarLexer 
from parser.CPPGrammarParser import CPPGrammarParser 

currenttimemillis = lambda: int(round(time.time() * 1000)) 

def is_string(object): 
    return isinstance(object,str) 

def parsecommandstringline(argv): 
    if(2!=len(argv)): 
     raise IndexError("Invalid args size.") 
    if(is_string(argv[1])): 
     return True 
    else: 
     raise TypeError("Argument must be str type.") 

def doparsing(argv): 
    if parsecommandstringline(argv): 
     print("Arguments: OK - {0}".format(argv[1])) 
     input = FileStream(argv[1]) 
     lexer = CPPGrammarLexer(input) 
     stream = CommonTokenStream(lexer) 
     parser = CPPGrammarParser(stream) 
     print("*** Parser: START ***") 
     start = currenttimemillis() 
     tree = parser.code() 
     print("*** Parser: END *** - {0} ms.".format(currenttimemillis()-start)) 
     pass 

def main(argv): 
    tree = doparsing(argv) 
    pass 

if __name__ == '__main__': 
    main(sys.argv) 

Das Problem ist, dass das Parsing sehr langsam ist. Bei einer Datei mit ~ 200 Zeilen dauert es mehr als 5 Minuten, während die Analyse der gleichen Datei in antlrworks nur 1-2 Sekunden dauert. den ANTLRWorks Baum Analyse, bemerkte ich, dass die expr Regel und alle seine Nachkommen sehr oft genannt werden, und ich denke, dass ich diese Regeln vereinfachen/ändern müssen schneller den Parser arbeiten zu machen: expr_tree

meine Annahme richtig oder habe ich beim Konvertieren der Grammatik einen Fehler gemacht? Was kann getan werden, um das Parsen so schnell wie auf antlrworks zu machen?

UPDATE: Ich exportierte die gleiche Grammatik nach Java und es dauerte nur 795ms, um das Parsen abzuschließen. Das Problem scheint mehr mit der Python-Implementierung als mit der Grammatik selbst zu tun zu haben. Gibt es etwas, das getan werden kann, um Python-Parsing zu beschleunigen?
Ich habe here gelesen, dass Python 20-30 mal langsamer als Java sein kann, aber in meinem Fall ist Python ~ 400 mal langsamer!

+0

Müssen Profil Regel Ausführungszeiten, um irgendeine Gewissheit zu haben. Könnte die starke Verwendung von negierten Mengen, Literalen im Parser oder etwas anderes sein, das völlig gutartig erscheint. – GRosenberg

+0

@GRosenberg danke für die kommentierung. Ich bin kein ANTLR-Experte, aber scheint mir nicht, dass meine Grammatik und das Original eine Menge negierter Sätze oder Literale im Parser haben. Ich denke, es ist ein Fehler im Zusammenhang mit 'antlr4-python2-runtime', da es nur 1 Sekunde dauert, um die gleiche Datei in Java zu parsen.Python kann langsamer sein, aber 400 mal langsamer ist zu viel um zu denken, dass es ein Problem auf meiner Seite ist. – Vektor88

+0

Der beste Weg, um den Aspekt der Laufzeit zu identifizieren, der nicht performant ist, besteht darin, die einzelnen Regeln zu profilieren und bestimmte Regelaspekte zu identifizieren, die langsam verarbeitet werden müssen. Das Problem ist auf Ihrer Seite nur in dem Sinne, dass Ihre Grammatik etwas unternimmt, um die Verlangsamung auszulösen. Fast unzweifelhaft ist eine Änderung der Laufzeit erforderlich. Der schwierige Teil ist herauszufinden, was zu beheben ist. Der Schlüssel liegt glücklicherweise irgendwo in deiner Grammatik. Tun Sie, was Sie können, um die Ursache zu isolieren und ein Problem im Antlr Github Repo zu erzeugen. Das ist der schnellste Weg, um es zu reparieren. – GRosenberg

Antwort

6

Ich bestätige, dass die Python 2 und Python 3 Laufzeiten Leistungsprobleme haben. Mit ein paar Patches habe ich eine 10x Beschleunigung auf der Python3 Runtime (~ 5 Sekunden bis ~ 400 ms). https://github.com/antlr/antlr4/pull/1010

+2

Die Pull-Anfrage wurde akzeptiert: Benutze die letzte antlr4-Python-Laufzeit oder warte auf die 4.5.3-Releases auf Pypi ... – Pinaraf

3

Ich stand vor einem ähnlichen Problem, also entschied ich mich, diesen alten Beitrag mit einer möglichen Lösung zu stoßen. Meine Grammatik lief sofort mit dem TestRig aber war unglaublich langsam auf Python 3.

In meinem Fall war der Fehler das nicht-gierige Token, das ich verwendet habe, um eine Zeile Kommentare (doppelter Schrägstrich in C/C++, '%') in meinem Fall): Verwendung von nicht-gierige Operatoren, vor allem in Parser Regeln https://github.com/antlr/antlr4/issues/658

Wenn Leistung ein Anliegen ist, vermeiden:

TKCOMM : '%' ~[\r\n]* -> skip ; 

Diese etwas durch diesen Beitrag von sharwell in dieser Diskussion hier gesichert .

Um dieses Szenario zu testen, möchten Sie möglicherweise nicht gierige Regeln/Token aus Ihrer Grammatik entfernen.

+0

Und was hast du benutzt, um eine bessere Kommentarregel zu haben? – DainDwarf

+0

@DainDwarf Im Moment bin ich Vorverarbeitung und Entfernen von Kommentaren in einer separaten Routine ohne ANTLR. Ich benutze dies als Workaround, bis der Performance Patch, der in diesem Thread zitiert wird, zu Ende geht. – Caian