正则表达式 – 解析大文件时为什么Scala的组合器解析速度慢?我能做什么?

我需要解析拥有数百万行的文件.我注意到我的组合器解析器变得越来越慢,因为它解析了越来越多的行.问题似乎是在
scala的“rep”或正则表达式解析器中,因为即使对于下面显示的简单示例解析器,也会出现这种情况:

def file: Parser[Int] = rep(line) ^^ { 1 }  // a file is a repetition of lines

def line: Parser[Int] = """(?m)^.*$""".r ^^ { 0 } // reads a line and returns 0

当我尝试使用这个简单的解析器解析具有数百万行等长的文件时,在开始时它会解析46行/ ms.在370000行之后,速度降至20行/ ms.在840000行之后,它下降到10行/ ms.经过1790000行,5行/ ms ……

我的问题是:

>为什么会这样?
>我该怎么做才能防止这种情况发生?

最佳答案 这可能是Java 7u6中没有子串作为原始字符串的一部分而发生变化的结果.这么大的字符串会一遍又一遍地被复制,导致大量的内存流失(以及其他事情).随着你增加你解析的东西的数量(我假设你至少存储了一些东西),垃圾收集器有越来越多的工作要做,所以创建所有额外的垃圾会有更陡峭和更陡的惩罚.

有一个ticket to fix the memory usage,来自Zach Moazeni的代码可以让你将你的字符串包装在一个构造中,该构造将正确地创建子字符串(你可以将它传递给解析器来代替字符串).

这不一定会改变解析最终减慢的总体结果,但它应该有助于减少总体时间.

此外,我不建议使文件重复行.您正在使解析器在不需要时跟踪整个文件.我一次喂它一行. (如果线条很短,你可能不需要上面的修复.)

点赞