Java 优化正则表达式

Java 优化正则表达式,java,regex,optimization,Java,Regex,Optimization,我正在使用以下代码来丢弃连接到大型ISP网络的路由器不支持的物理接口/子接口(我指的是数以万计的路由器): private final静态模式接口到过滤器= 模式编译(“未路由VLAN |千兆以太网+-mpls层|快速以太网+-802\\.1Q VLAN子IF”); //简化 列出接口; //大量不相关的代码用于查询路由器 for(字符串intf:接口){ if(接口\u到\u FILTER.matcher(intf.find()){ //防止使用接口的代码 } } 我们的想法是放弃以下条目

我正在使用以下代码来丢弃连接到大型ISP网络的路由器不支持的物理接口/子接口(我指的是数以万计的路由器):

private final静态模式接口到过滤器=
模式编译(“未路由VLAN |千兆以太网+-mpls层|快速以太网+-802\\.1Q VLAN子IF”);
//简化
列出接口;
//大量不相关的代码用于查询路由器
for(字符串intf:接口){
if(接口\u到\u FILTER.matcher(intf.find()){
//防止使用接口的代码
} 
}
我们的想法是放弃以下条目:

  • GigabitEthernet2/11.2000的未路由VLAN 2000
  • 千兆以太网1/2-mpls层
  • FastEthernet6/0/3.2000-802.1Q vLAN子接口
这段代码在庞大的接口集(一些路由器有50k+子接口)上经常被命中(每分钟几次),缓存也没有多大帮助,因为新的子接口经常被配置/丢弃。计划是优化正则表达式,使过程完成得更快一点(每纳秒计数一次)。你们能启发我吗


注意:
mpls层
802.1Q
支持其他类型的接口,
未路由的VLAN
不受支持。

有一些字符串搜索算法,允许您尝试在长度为n的字符串中搜索k个字符串,同时比明显的O(n*k)成本更低

他们通常将滚动哈希与单词的现有哈希列表进行比较。这方面的一个主要例子是。wiki页面甚至有一个关于这一点的部分。还有更高级的原理版本,但很容易理解

不知道Java中是否已经有这样的库(我想是的),但我会尝试这样做——虽然这里5个字符串相当小(不同的大小也使它更复杂)。所以最好检查一个好的KMP字符串搜索是否更快——我认为这是目前为止最好的解决方案(默认的JavaAPI使用简单的字符串搜索,所以使用lib)

关于您的正则表达式:针对性能关键型搜索代码的回溯正则表达式实现?我怀疑这是个好主意


附言:如果你为你的问题发布一个测试集和一个测试工具,很有可能有人会看到他们能在多大程度上击败最受欢迎的人,他们以前做过。。人性很容易被欺骗:)

如果你的问题是你有很多长字符串常量要搜索,我建议你使用Java模拟的标准C工具“lex”


快速的谷歌搜索把我带到了。我没有使用过此特定工具,可能还有其他可用工具,但这是我要寻找的工具类型的一个示例。

如果您必须为此使用正则表达式,请尝试更改为此工具:

^(?:unrouted VLAN)|(?:GigabitEthernet.+?-mpls layer)|(?:FastEthernet.+?-802\.1Q vLAN subif)
^
使引擎从字符串开始匹配,而不是字符串中的任何位置

+?
使
+
解除冻结


(?:…)
makes
()
非捕获组

我在回答我自己的问题,以供进一步参考,尽管学分归@piotrekkr,因为他是指明方向的人。我也为@JB和@ratchet感到荣幸。我最终使用了
matches()
,而使用
indexOf
和几个
contains
的逻辑几乎同样快(这对我来说是新闻,我一直认为一个正则表达式比几个
contains
调用要快)

下面是一个速度快了好几倍的解决方案(根据profiler,在
Matcher
类方法上花费的时间减少了约7倍):


为什么不先分离出应该匹配的字符串,并检查您是否只使用了string.contains而不是regex?您提供的这些条目是完整的行或从行中间提取的一些单词?我不知道,但很容易测试它是否值得。您也可以使用indexOf,只测试在“GigabitEthernet”索引+15(15是“GigabitEthernet”的长度)之后找到“-mpls-layer”,这样就不会
matches()
工作,这不会在每个位置都尝试(只尝试了1个匹配,而不是
intf.length()
),谢谢@Voo。我会深入研究的。至于测试工具,我不确定我能做什么,可能会在这些树字符串上迭代5.000.000次,并用
System.nanotime()
:D记录时间。我对基准测试lol不太满意。如果明天我对它不满意,我会用测试lol:D更新代码。@Anthony Yeah用java编写基准测试并不容易。应该让它更容易,但我没用过。如果你想要一个合理的基准测试,克里夫的其中一个应该会对你有所帮助。一般来说,我建议:一个接口
boolean valid(String s)
,由候选测试实现,然后你只需检查一些典型的输入字符串(并检查结果!)。最简单的方法是从您单独提供的文件中读取输入,毕竟它应该是您常用数据的代表,所以我们不能在那里生成随机字符串。总的来说:永远不要优化你无法衡量的东西,所以这真的应该是你要做的第一件事。。别担心,如果您发布第一个版本,我们会指出一些问题;-)哈哈哈。。。这就是为什么我不写基准测试。。。我正在使用一个分析器来测量我自己的代码:D.@Anthony,这也行得通,尽管根据我的经验,比较大型应用程序之间的运行是一个相当大的问题——即相同的代码,相同的数据从一个调用到另一个调用会运行快20%或慢20%——这就是JITing、OSR等的问题。但是对于较大的差异,使用探查器应该给出一个比较准确的图片是的。好吧,lex最终会为他创建一个FSM,好吧。。正则表达式已经在做这件事了…说得好。我想使用lex工具有两个原因:(1)我希望该工具能更好地处理optimi
^(?:unrouted VLAN)|(?:GigabitEthernet.+?-mpls layer)|(?:FastEthernet.+?-802\.1Q vLAN subif)
^(?:unrouted VLAN.++|GigabitEthernet.+?-mpls layer|FastEthernet.+?-802\\.1Q vLAN subif)$