有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

正则表达式在中的性能。NET vs Java

我在解析大型文本文件时遇到了正则表达式性能问题
我正在使用。NET 4.0,代码如下:

private static pattern =   
@"((\D|^)(19|20|)\d\d([- /.\\])(0[1-9]|1[012]|[1-9])\4(0[1-9]|[12][0-9]|3[01]|[0-9])  (\D|$))|" +
@"((\D|^)(19|20|)\d\d([- /.\\])(0[1-9]|[12][0-9]|3[01]|[0-9])\11(0[1-9]|1[012]|[0-9])  (\D|$))|" + 
@"((\D|^)(0[1-9]|1[012]|[0-9])([- /.\\])(0[1-9]|[12][0-9]|3[01]|[0-9])\18(19|20|)\d\d(\D|$))|" + 
@"((\D|^)(0[1-9]|[12][0-9]|3[01]|[0-9])([- /.\\])(0[1-9]|1[012]|[0-9])\25(19|20|)\d\d(\D|$))|" + 
@"((\D|^)(19|20|)\d\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])(\D|$))|" + 
@"((\D|^)(19|20|)\d\d(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])(\D|$))|" + 
@"((\D|^)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])(19|20|)\d\d(\D|$))|" + 
@"((\D|^)(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])(19|20|)\d\d(\D|$))|" + 
@"((^|(?<!(\d[- /.\\\d])|\d))(19|20|)\d\d([- /.\\])(0[1-9]|1[012]|[1-9])([^- /.\\\d\w]|$|\s))|" + 
@"((^|(?<!(\d[- /.\\\d])|\d))(0[1-9]|1[012]|[1-9])([- /.\\])(19|20|)\d\d([^- /.\\\d\w]|$|\s))|" + 
@"((^|(?<!(\d[- /.\\\d])|\d))(0[1-9]|1[012]|[1-9])([- /.\\])(0[1-9]|[12][0-9]|3[01])([^- /.\\\d\w]|$|\s))|" + 
@"((^|(?<!(\d[- /.\\\d])|\d))(0[1-9]|[12][0-9]|3[01])([- /.\\])(0[1-9]|1[012]|[1-9])([^- /.\\\d\w]|$|\s))"; 

private static Regex dateRegex = new new Regex(pattern, 
    RegexOptions.Compiled | RegexOptions.IgnoreCase | 
    RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

public static void Extract(string text)  
{
   foreach (Match match in dateRegex.Matches(text))
                Console.Writeline("Match {0}",match.Value);
}

包含200个匹配项的1MB文本文件的处理时间约为22秒
用Java运行相同的正则表达式会产生更快的结果:~13秒
我成功地缩短了文件的处理时间。NET代码,将正则表达式拆分为多个部分并并行执行
为什么Java处理这个正则表达式要快得多
我能做些什么来提高效率。处理这个正则表达式的净性能

干杯,
多伦


共 (2) 个答案

  1. # 1 楼答案

    我现在没有时间完成我的分析,但我会提供到目前为止的进展。这是重新格式化的正则表达式,这样您就可以真正阅读它了。我所做的唯一改变是在字符类中包装一些空格,以允许自由间隔模式。共有80个俘虏小组(Yipes!-其中大部分似乎没有必要)。这个表达式似乎与日期的各种形式相匹配。还有很多有待改进的地方:

    private static pattern = @"
        # Match various forms of a Date.
          (                                     # Begin $1:
            (\D|^)                              # $2:
            (19|20|)\d\d                        # $3:
            ([- /.\\])                          # $4:
            (0[1-9]|1[012]|[1-9])               # $5:
            \4
            (0[1-9]|[12][0-9]|3[01]|[0-9])      # $6:
            [ ][ ]
            (\D|$)                              # $7:
          )                                     # End $1:
        | (                                     # Begin $8:
            (\D|^)                              # $9:
            (19|20|)\d\d                        # $10:
            ([- /.\\])                          # $11:
            (0[1-9]|[12][0-9]|3[01]|[0-9])      # $12:
            \11
            (0[1-9]|1[012]|[0-9])               # $13:
            [ ][ ]
            (\D|$)                              # $14:
          )                                     # End $8:
        | (                                     # Begin $15:
            (\D|^)                              # $16:
            (0[1-9]|1[012]|[0-9])               # $17:
            ([- /.\\])                          # $18:
            (0[1-9]|[12][0-9]|3[01]|[0-9])      # $19:
            \18
            (19|20|)\d\d                        # $20:
            (\D|$)                              # $21:
          )                                     # End $15:
        | (                                     # Begin $22:
            (\D|^)                              # $23:
            (0[1-9]|[12][0-9]|3[01]|[0-9])      # $24:
            ([- /.\\])                          # $25:
            (0[1-9]|1[012]|[0-9])               # $26:
            \25
            (19|20|)\d\d                        # $27:
            (\D|$)                              # $28:
          )                                     # End $22:
        | (                                     # Begin $29:
            (\D|^)                              # $30:
            (19|20|)\d\d                        # $31:
            (0[1-9]|1[012])                     # $32:
            (0[1-9]|[12][0-9]|3[01])            # $33:
            (\D|$)                              # $34:
          )                                     # End $29:
        | (                                     # Begin $35:
            (\D|^)                              # $36:
            (19|20|)\d\d                        # $37:
            (0[1-9]|[12][0-9]|3[01])            # $38:
            (0[1-9]|1[012])                     # $39:
            (\D|$)                              # $40:
          )                                     # End $35:
        | (                                     # Begin $41:
            (\D|^)                              # $42:
            (0[1-9]|1[012])                     # $43:
            (0[1-9]|[12][0-9]|3[01])            # $44:
            (19|20|)\d\d                        # $45:
            (\D|$)                              # $46:
          )                                     # End $41:
        | (                                     # Begin $47:
            (\D|^)                              # $48:
            (0[1-9]|[12][0-9]|3[01])            # $49:
            (0[1-9]|1[012])                     # $50:
            (19|20|)\d\d                        # $51:
            (\D|$)                              # $52:
          )                                     # End $47:
        | (                                     # Begin $53:
            ( ^                                 # Begin $54:
            | (?<!
                (\d[- /.\\\d])                  # $55:
              | \d
              )
            )                                   # End $54:
            (19|20|)\d\d                        # $56:
            ([- /.\\])                          # $57:
            (0[1-9]|1[012]|[1-9])               # $58:
            ([^- /.\\\d\w]|$|\s)                # $59:
          )                                     # End $53:
        | (                                     # Begin $60:
            ( ^                                 # Begin $61:
            | (?<!
                (\d[- /.\\\d])                  # $62:
              | \d
              )
            )                                   # End $61:
            (0[1-9]|1[012]|[1-9])               # $63:
            ([- /.\\])                          # $64:
            (19|20|)\d\d                        # $65:
            ([^- /.\\\d\w]|$|\s)                # $66:
          )                                     # End $60:
        | (                                     # Begin $67:
            ( ^                                 # Begin $68:
            | (?<!
                (\d[- /.\\\d])                  # $69:
              |\d
              )
            )                                   # End $68:
            (0[1-9]|1[012]|[1-9])               # $70:
            ([- /.\\])                          # $71:
            (0[1-9]|[12][0-9]|3[01])            # $72:
            ([^- /.\\\d\w]|$|\s))               # $73:
        | (                                     # Begin $74:
            ( ^                                 # Begin $75:
            | (?<!
                (\d[- /.\\\d])                  # $76:
              | \d
              )
            )                                   # End $75:
            (0[1-9]|[12][0-9]|3[01])            # $77:
            ([- /.\\])                          # $78:
            (0[1-9]|1[012]|[1-9])               # $79:
            ([^- /.\\\d\w]|$|\s)                # $80:
          )                                     # End $74:
        ";
    

    当我有更多的时间时,我会用一些建议的改进来更新这个答案。同时,其他regex专家请随意使用这个改进的部分评论版本并使用它运行

  2. # 2 楼答案

    有不同风格的正则表达式解析器,java解析器可能更适合您使用的模式。但是你的模式和你选择的选项真的会让这个慢下来

    RegexOptions。IgnoreCase(有必要吗?)See Want faster regular expressions? Maybe you should think about that IgnoreCase option...

    RegexOptions。IgnorePatternWhitespace:您没有模式空白。这不会减慢实际的正则表达式解析,因为它只允许用户记录模式。但这很有说服力,因为它表明模式的创建者(无意冒犯,这里真的是:-)不理解正则表达式解析器需要什么才能在合理的时间内有效地执行模式请参阅下一个声明,了解其缓慢的原因

    你的模式是慢的,因为模式的模糊性会导致太多回溯问题;简单明了

    有关这意味着什么的更多信息,请参见Backtracking