如何在不使用Java创建对象的情况下匹配正则表达式



我正在开发一个reg表达式匹配函数。问题是,这个函数将被嵌套循环中的框架调用。如果创建了临时对象,GC将导致非常大的性能问题。

是否可以在不创建临时对象(Pattern、Matcher)的情况下处理regexp?重写regexp类是我最后的选择。。。

引用一句老话:

让它发挥作用,让它正确,让它快速。(按顺序)

因此,在进行任何繁重的验光步骤之前,只需编写最初的简单适当的代码(在这种情况下,如果可以的话,这将涉及预编译您的模式)。运行一些测试,看看性能是否不足,然后优化regex部分是否是瓶颈。

如果对象创建(和清理)是一个严重的瓶颈(与实际的regex解析本身相比),那么您可能需要实现自己的使用对象池的解决方案(因此不会创建对象,只需从池中重置和重用对象)。不过,我怀疑这是否会带来任何严重的性能提升,所以您应该首先进行基准测试,看看有多少提升是可能的(如果您将对象创建/清理性能提高了50%,这值得吗?)。

您最好的选择是在问题出现时及时处理,而他们可能不会这样做。在大约十年前,GC处理大量小生命物体的性能问题是一个问题,但现在它非常擅长

如果你确实需要优化,那么这应该是以改变GC选项的形式——例如年轻一代的规模,而不是试图在代码中优化。

Matcher对象不是线程安全的,因此除非调用reset()方法(在单个线程中应该可以正常工作),否则不能重用它们-请参阅Java Regex线程安全吗?

这听起来像是过早的优化。

尽可能编写最简单的代码,然后在现实的环境中对其进行评测,并查看性能或内存分配模式是否存在任何问题。如果有的话,解决你发现的具体问题。

现代JVM非常擅长垃圾收集短命对象。

您可以预编译正则表达式,如果您多次重用同一个正则表达式,这是有意义的。

代替

boolean foundMatch = subjectString.matches("a.*b");

(无论如何都会创建临时编译的Pattern),您可以使用

Pattern regex = Pattern.compile("a.*b");
// loop here
// do something...
    Matcher regexMatcher = regex.matcher(subjectString);
    boolean foundMatch = regexMatcher.matches()
// loop end

不过,很难说是否会有任何相关的性能优势。

在我看来,你有两个可行的选择:

  1. 通过查看源代码:Pattern和Matcher,编写自己的正则表达式匹配逻辑
  2. 在处理完这些对象后,显式地启动它们的集合,方法是运行它们对应的finalize()函数,而不是等待GC运行它

优点和缺点

  1. 很多工作,需要在未来进行测试和维护,但你可以完全控制你想要做的事情

  2. 不建议干扰GC、清洁溶液和简单溶液的工作

最新更新