【问题标题】:profiling a simple regex search分析一个简单的正则表达式搜索
【发布时间】:2013-12-16 01:58:24
【问题描述】:

我想在 perl 中测试两种不同方法的性能,即检查一个字符串是否完全包含在另一个字符串中。

第一种方法是将字符串转换为数组并逐个字符进行测试,而第二种方法只是评估正则表达式(我相信它的顺序与线性搜索所有字符的顺序相同,但不产生为数组分配内存并将字符复制到其中的成本(尽管它可能涉及其他成本))。

我最初进行此测试的方法是将两个程序(见下文)放入一个大的 for 循环(0 到 999999)中,然后计算程序完成所需的时间;起初看起来正则表达式匹配要快得多(12.926s vs 0.318s);但是我随后考虑了在评估正则表达式时,一旦以下迭代是微不足道的,因为它被缓存了。为了测试这一点,我将我的 for 循环放在命令行上(使 perl 脚本的每次迭代循环通过 0 到 0“无内存”)并注意到它们都是相似的(尽管有时与平均值有一些巨大的差异)。但我强烈怀疑这可能是一个糟糕的结论,因为启动脚本所花费的时间可能会主导脚本的执行时间。

有没有办法(特别是当我想看一些不那么琐碎的东西时)关闭缓存(如果这是当然发生的事情),这样我就可以在 for 循环中公平地运行程序(这样我就可以只调用一次脚本)?

或者在这个例子中没有什么聪明的事情发生并且正则表达式搜索真的快得多!?

my $teststr = "testing testing";
my $teststr2 = "testing tasted";
my $match = 1;

#procedure one - character by character checking
for (my $i = 0; $i < 1; $i++)
{
    my @chrArr = split //, $teststr;
    my @chrArr2 = split //, $teststr2;
    for (my $j = 0; $j < @chrArr2; $j++)
    {
        if($chrArr[$j] != $chrArr2[$j])
        {
            $match = 0;
            break;
        }
    }
}

#procedure 2 - regex matching
for (my $i = 0; $i < 1; $i++)
{
    if($teststr !~ m/$teststr2/)
    {
        $match = 0;
    }
}

【问题讨论】:

  • 你应该看看Benchmark模块。
  • 这看起来很有用 - 谢谢,我会玩的
  • 现在播放完成(好工具!)...这两种方法(n=10^7)的时间是 5.11s 用于 char-by-char(包括数组复制)和 2.99正则表达式。这更符合我的预期(我第一次测试的 40 倍看起来太好了)

标签: regex perl


【解决方案1】:

为什么不使用 Banchmark 模块。它应该非常适合这里。

使用基准 qw(timethese cmpthese);

-- 微信

【讨论】:

  • 谢谢,这是之前在评论中提出的建议,我玩过它 - 这是一个不错的工具。
【解决方案2】:

正则表达式匹配/搜索是线性的。编译模式很昂贵。如果每次迭代都更改 $teststr2,则无法进行缓存。例如:

#procedure 2 - regex matching
for (my $i = 0; $i < 1; $i++)
{
    if($teststr !~ m/${i}$teststr2/)
    {
        $match = 0;
    }
}

【讨论】:

  • 太好了,谢谢你。对于它的价值,在这个例子中,正则表达式评估的 1000000 次迭代需要 2.519 秒(看起来更合理),而一个字符一个字符的检查需要 12.926 秒(对于在第一种方法中多个搜索主导数组分配的更复杂的事情,我可能会看到不同的东西)
  • 实际上是为了让测试更公平,这次我让逐字符搜索只查看内部 for 循环中的第一个字符(因为我希望正则表达式对于空变量总是会很快失败)。这次第一种方法的执行时间为 6.392 秒(数组分配将在这里占主导地位 - 实际上将数组设置拉出循环执行时间是第一种方法的 0.598 秒)。
  • @HexedAgain:您似乎正在寻找阻碍正则表达式匹配的方法,试图使其像循环单个字符一样慢。在 Krico 的代码中,您正在计时的内容包括将数字 $i 转换为字符串、连接两个字符串以及编译正则表达式。您真的希望针对一百万个不同模式进行测试,以便每次正则表达式都不同吗?正则表达式更快,主要是因为这是使用它们的要点之一。你在最初的测试中得到的 40 倍对我来说似乎是正确的。你还想证明什么?
  • @krico:是的,编译正则表达式通常比模式匹配本身更耗时,但是您希望在这里证明什么?期望每种模式都不同是不现实的,这就是一次性编译开销值得的原因。如果您添加任意额外的工作只是为了减慢循环速度,那么您不妨使用sleep
  • @krico:另外,正则表达式匹配不是线性的。尝试/a\z/ 对抗任何长度的字符串,我敢打赌你会在同一时间得到。
猜你喜欢
  • 1970-01-01
  • 2012-01-01
  • 2011-03-23
  • 2017-08-12
  • 2011-12-19
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
  • 2014-03-22
相关资源
最近更新 更多