用于LARGE文件的ANTLR4技术 - 分解解析树

时间:2017-02-28 16:59:24

标签: java parsing out-of-memory antlr4

如果我使用-Xmx8G将JAVA VM大小设置为8G,那么我有一个工作的ANTLR4编译器,适用于高达~300Mb的文件。但是,较大的文件会使解析器/编译器因HEAP内存不足而崩溃。我被建议在ANTLR4进程之外检查我的代码以获取内存消耗。 (下面的数据)我正在使用令牌工厂和unbufferedChar和令牌流。

我正在使用的一个策略是测试INPUT文件/流的大小(如果可知的话),就我的情况而言。如果文件很小,则使用我的顶级规则进行解析,该规则生成一个很大的解析树,但适用于小文件。

如果文件大于任意阈值,我尝试通过选择子规则将解析分成块。因此,对于小文件,我解析规则patFile(现有的工作代码),对于大型文件,我正在通过解析子规则“patFileHeader”来解决问题,然后解析规则“bigPatternRec”,它取代了“pattern +”部分。以前的规则。 通过这种方式,我的期望是我可以控制读取多少令牌流。

目前这看起来很有希望,但我看到控制ANTLR4在处理标头时解析了多少问题。我可能有一个语法规则,导致patFileHeader在退出之前使用所有可用的输入标记。其他情况似乎有效,但我还在测试。我只是不确定这种解决“大文件”解析的方法是否可行。

SMALL文件示例语法:

patFile         :   patFileHeader patterns+
//                  {System.out.println("parser encountered patFile");}
                ;
patFileHeader   :   SpecialDirective? includes* gbl_directives* patdef  
                ;               
patterns        :   patdata+ patEnd
//                  {System.out.println("parser encountered patterns");}
                ;
bigPatternRec   :   patdata 
                |   patEnd
                ;
...

在我的小文件的情况下,我用:

创建解析树
   parser = new myparser(tokens);
   tree = parser.patFile();           // rule that parses to EOF
   walker=walk(mylisteners,tree);

将整个文件解析为EOF。

对于较大的文件,我考虑了以下技术:

  // Process the first few lines of the file
  tree = parser.patFileHeader();     // sub rule that does not parse to EOF
  walker=walk(mylisteners,tree);

  //
  // Process remaining lines one line/record at a time
  //
  while( inFile.available() ) {
          parser = new myParser(tokens);
          tree = parser.bigPatternRec();
          walker=walk(mylisteners,tree);
  }

在回应我描述行为的建议时,我在处理项目期间在“整个文件”上生成了JVMonitor的屏幕截图。 对我来说有一点感兴趣的是三个上下文集~398Mb。在我的语法中,vec是vecdata的一个组件,因此看起来某些上下文数据正在被复制。我可以玩那个。 char []条目可能是我在ANTLR4之外的代码。我必须禁用我的监听器并运行以生成解析树,而不管我的代码是否有效。我做其他消耗内存(MappedByteBuffers)的东西,用于输出上的高速文件I / O,这将有助于超过8Gb图像。 JVMMonitorShot

有趣的是,如果我打破调用并且只是处理子规则,内存映像会发生什么。内存消耗大约为全尺寸的10%,在这种情况下,ANTLR4对象甚至不在雷达上。 SubruleJVMMonitor

0 个答案:

没有答案