【记录】尝试优化antlr的lexer和parser以提高继续速度(解析性能)

【背景】

之前已经写好了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.这里:

ANTLR performance

提到了,说是关闭了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的,看看性能是否提升,结果看到:

Why do we need 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

‘READ’=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.待后续继续折腾。。。



发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量