【背景】
之前已经写好了antlr的语法,去解析eddl。
但是,当eddl文件很大,比如6000+行,149KB,的时候,解析起来,极其的慢,在i5-2400(3.1GHz)+8G内存+win7 x64的情况下,都需要解析很长时间,以分钟计算的那种时间。
以至于,用antlrworks 1.5rc2,去解析6000+行eddl时,都导致antlrworks死掉,没反应,然后过了N分钟后,解析完毕后,才可以正常操作。。。。
而不是希望能够达到,就像解析几十行,几百行的eddl一样的,只需要多少秒即可解析完毕。
现在,尝试找找,什么方法,可以优化antlr的(lexer和parser)的解析速度,提供性能,减少解析的时间。
【折腾过程】
1.参考:
[antlr-interest] Token parsing speed
感觉其中说的不是很靠谱。
因为即使对于:
rule1: FIRST; rule2: FIRST WS SECOND; FIRST: 'first'; SECOND: 'second' WS: ' ';
如果中间有多个空格,但是WS,也是无法匹配的,也要改为WS+才可以的。
而且,目前已知的是:
parser的rule中,最好,不要有literal。
2.参考:
[antlr-interest] Lexer speed comparison
提到antlr v2性能慢,然后作者parr说是antlr 3.0性能会有提升。
但是我目前就是用的antlr v3啊。。。
3. 然后其中也提到了,用syntactic predicates会导致性能下降。
我此处,就用到了,但是暂时不方便去除,所以这点上,没啥优化的了。
4.这里:
提到了,说是关闭了rewrite rule,就可以提升性能x100
我这里,貌似暂时没遇到rewrite rule,所以暂时可以忽略这方面的优化。
注:其是,25kb文件,需要10秒,希望变成0.5秒。
5.随便测试一下,设置k为某个值,比如k=3:
options { output = AST; ASTLabelType = CommonTree; // type of $stat.tree ref etc... k=3;//debug performance }
看看能否正常解析,是否对性能有影响。
结果是,貌似看不出来有何影响。因为解析时间貌似同样的长。。。
6.看到:
Poor performance of expression parsing
但是也看不懂。。。
7.参考:
[antlr-interest] "RE: ANTLR performance
但是看不太懂。
其中看到有个词:Sempreds和synpreds,
8.随便再去试试filter=true:
options { output = AST; ASTLabelType = CommonTree; // type of $stat.tree ref etc... //k=3;//debug performance filter=true;//debug performance }
结果直接出错:
[17:37:11] error(133): HartEddl.g:9:1: illegal option filter |
估计此处是combined grammar(包含了parser)所导致的。所以放弃。
9.本来还打算抽空试试antlr v4的,看看性能是否提升,结果看到:
中的:
Another big thing with v4 is that my goal has shifted from performance to ease-of-use. |
所以,看来antlr v4的性能,估计也不会比antlr v3好到哪里去,所以直接放弃此想法了。
10.后来,想到了,之前的:
【已解决】antlr v4的语法出错:line 1:0 mismatched input ‘a’ expecting A
而得之的:
parser的rule中,最好不要有literal
所以,可以抽空试试,把所有的,parser中的rule中的literal,都弄成对应的token,试试速度是否会提高。
对应的,目前,生成的tokens文件中,很多都是重复的,比如:
HartEddl.tokens中有:
T__114=114 |
对应的是HartEddlLexer.java中的:
// $ANTLR start "T__114" public final void mT__114() throws RecognitionException { try { int _type = T__114; int _channel = DEFAULT_TOKEN_CHANNEL; // D:\\DevRoot\\IndustrialMobileAutomation\\HandheldDataSetter\\ANTLR\\projects\\v1.5\\HartEddlParser_local_TFS\\HartEddl.g:83:8: ( 'READ' ) // D:\\DevRoot\\IndustrialMobileAutomation\\HandheldDataSetter\\ANTLR\\projects\\v1.5\\HartEddlParser_local_TFS\\HartEddl.g:83:10: 'READ' { match("READ"); } state.type = _type; state.channel = _channel; } finally { // do for sure before leaving } } // $ANTLR end "T__114"
所以,应该把:
‘READ’=114 |
消除掉才对,去改为对应的token,单独定义此literal。
这个,等抽空,再全部都改掉吧,因为,目测,需要很长时间的。。。
11.待后续继续折腾。。。