[antlr-interest] ANTLR 3.1 - Serious performance downgrade

Benjamin Niemann pink at odahoda.de
Sun Aug 17 13:19:43 PDT 2008


Hi Michael,

there has been a major change to the implementation of the
TokenRewriteStream. I quick look at the code suggests, that
TokenRewriteStream.reduceToSingleOperationPerIndex() is O(n^2), where
n is the number of rewrites - and it is called for each toString call.
Did you do some profiling to find the method that takes most of the
time?

-Ben


On Sun, Aug 17, 2008 at 9:52 PM, Dr. Michael Gerz
<michael.gerz at teststep.org> wrote:
> Dear ANTLR developers, hi Terence,
>
> when upgrading to the latest and greatest ANTLR 3.1, we noticed a
> significant performance downgrade that makes it almost unuseable for our
> purposes.
>
> In our system, we use a grammar that is a modified version of the 'Java'
> grammar given on the ANTLR web page, with some minor test-specific
> extensions and a few simplifications. By means of a ANTLR tree grammar
> (using StringTemplate), we transform these extensions to plain Java.
>
> In the past, the transformation times were neglectable (within the range of
> a few seconds). However, with ANTLR 3.1 final, converting a 679KB input file
> into a 735KB Java file takes about 10 minutes!
>
> I tried to identify the problem and came up with the following conclusions:
>
> * The performance slowdown happens in our tree grammar. The ANTLR
>  parser and lexer are pretty fast.
> * The showstopper was introduced sometime between intermediate release
>  antlr-2008-05-25.11.tar.gz (fast) and antlr-2008-08-03.16.tar.gz (slow).
> * The performance seems to decrease exponentially with the input size.
>
> Below please find the header of our tree grammar and the method that invokes
> it.
>
> Does anybody have any idea why ANTLR has become so extremely slow just
> before its final release? I am sure that this must be a general problem that
> also affects other people. Is there anything else that you need to analyse
> the problem?
>
> Thanks in advance!
>
> Michael
>
>
>
> ++++++ Snippet from JavaCodeGenerator.g ++++++
>
> tree grammar JavaCodeGenerator;
>
> options {
>       k = 1;
>       ASTLabelType = CommonTree;
>       tokenVocab = TestLang;
>       output = template;
>       rewrite = true;
>   }
>
> ... some scope definitions ...
>
> @members {
>
>   ... some member definitions ...
> }
>
> @header {
>   package de.fgan.fkie.sylt.testsystem.testlang;
>
>   ... some import declarations ...
> }
>
> ... the start rule ... where needed, string templates are used ...
>
> compilationUnit
>   :    idecls+=importDeclaration*
>       (    tsd=testsuiteDeclaration
>           -> template(ids={$idecls}, tsd={$tsd.text})
> <<
> package de.fgan.fkie.sylt.test;
>
> import de.fgan.fkie.sylt.testsystem.server.testrunner.TestRunner;
>
> <ids>
> <tsd>
>>>
>       |    tgd=testgroupDeclaration
>           -> template(ids={$idecls}, imp={getImportStatements()},
> tgd={$tgd.text})
> <<
> package de.fgan.fkie.sylt.test;
>
> <imp>
>
> <ids>
> <tgd>
>>>
>       )
>   ;
>
> ... and so on ...
>
>
> ++++++ Invocation of JavaCodeGenerator ++++++
>
>
>   private static void saveAsJava(String testGroupName, String script) {
>       ANTLRInputStream input;
>       try {
>           input = new ANTLRInputStream(new
> ByteArrayInputStream(script.getBytes()));
>           TestLangLexer lexer = new TestLangLexer(input);
>           TokenRewriteStream tokens = new TokenRewriteStream(lexer);
>           TestLangParser parser = new TestLangParser(tokens);
>           TestLangParser.compilationUnit_return r;
>           try {
>               r = parser.compilationUnit();
>           } catch (RecognitionException e) {
>               throw new RuntimeException("Error while parsing " +
> testGroupName + ":"
>                       + parser.getErrorMessage(e,
> TestLangParser.tokenNames));
>           }
>           CommonTree t = (CommonTree) r.getTree();
>           CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
>           nodes.setTokenStream(tokens);
>           JavaCodeGenerator codeGen = new JavaCodeGenerator(nodes);
>
>           JavaCodeGenerator.compilationUnit_return r2;
>           try {
>               r2 = codeGen.compilationUnit();  /// SLOOOOOW, SOOO SLOOOOOW
>           } catch (RecognitionException e) {
>               throw new RuntimeException("Error while parsing " +
> testGroupName + ":"
>                       + codeGen.getErrorMessage(e,
> JavaCodeGenerator.tokenNames));
>           }
>
>           File f = new File(ServerProperties.SERVER_TEST_CLASS_DIRECTORY +
> File.separator
>                   + testGroupName + ".java");
>           FileWriter out = new FileWriter(f);
>           out.write(r2.st.toString());
>           out.close();
>
>       } catch (IOException e) {
>           throw new RuntimeException("Error while reading/writing " +
> testGroupName + ":"
>                   + e.getMessage(), e);
>       }
>   }
>
>
>
>


More information about the antlr-interest mailing list