代码之家  ›  专栏  ›  技术社区  ›  lisprogtor

perl6 regex子规则和命名的regex比显式regex慢得多;如何使它们同样快速?

  •  8
  • lisprogtor  · 技术社区  · 6 年前

    我有一个1608240行的数据文件。文件分为多个部分。每个部分在开始行中都有一个唯一的词,所有部分的最后一行中都有相同的词“donesection”。

    我正在尝试通过执行以下操作(代码由@raiph重新格式化,来自 original post ,使代码更容易解释):

    # using named subrules/regex is EXTREMELY slow;
    # it reads about 2 lines per second, and grinds to halt
    # after about 500 lines: (>> is the right word boundary)
    perl6 -e 'my regex a { [ <{<iron copper carbon>.join("||")}> ] };
              my $x = 0;
              for "/tmp/DataRaw".IO.lines {
                $*ERR.print( "$x 1608240 \r" );
                ++$x;
                .say if m/:i beginSection \s+ <a> >>/ or
                        (m/:i \s+ <a> \s+ /
                         ff
                         m/:i doneSection/);
              }'
    
    # however, if I explicitly write out the regex instead of using a subrule,
    # it reads about 1000 lines per second, and it gets the job done:
    perl6 -e 'my $x = 0;
              for "/tmp/DataRaw".IO.lines {
                $*ERR.print( "$x 1608240 \r" );
                ++$x;
                .say if m/:i beginSection \s+
                             [ iron || copper || carbon ] >>/ or
                        (m/:i \s+
                             [ iron || copper || carbon ] \s+ /
                         ff
                         m/:i doneSection/);
              }'
    

    我的问题是,如何使子规则和显式正则表达式一样快,或者至少不要陷入停顿?我更喜欢使用更高层次的抽象。这是Regex引擎内存问题吗?我还尝试使用:

    my $a=rx/ [ <{ < iron copper carbon > .join("||") }> ] /
    

    速度也一样慢。

    我无法发布160万行数据文件,但您可能可以生成类似的文件用于测试。

    谢谢你的提示。

    1 回复  |  直到 6 年前
        1
  •  6
  •   raiph    6 年前

    [ <{<iron copper carbon>.join("||")}> ]
    

    [ iron || copper || carbon ]
    

    my regex a { || < iron copper carbon > }
    

    < iron copper ... <iron copper ...> iron copper as it does in the main language

    my @matchers = < iron copper carbon >;
    my regex a { || @matchers }
    

    @matchers

    my @matchers = / i..n /, / cop+er /, / carbon /;
    my regex a { || @matchers }
    

    regex interpolation

    Big O

    my $a=rx/ [ <{ < iron copper carbon > .join("||") }> ] /
    

    <{ ...  }>
    

    DSLs

    use MONKEY-SEE-NO-EVAL; use MONKEY; pragma