c++ - Perl 正则表达式运行速度快于 C++ Boost 实现

标签 c++ regex perl boost

我对这里发生的事情有点困惑。我见过的大多数基准测试表明 Boost 在性能方面接近于 Perl,甚至超过它。然而,在我的脚本中,我的 Perl 实现速度快了 5-6 倍。

我在 test_script.cpp 和 test_script.pl 中打开文件并逐行读取,填充一个数组。然后,我针对线性定义中的正则表达式定义列表运行这些字符串,直到它们匹配,在这种情况下什么也没有发生(出于测试目的删除了 I/O),然后比较下一个字符串,等等,直到我们比较了所有字符串.

测试脚本.pl:

#make incomingList, which contains all incoming strings
my $start = Time::HiRes::gettimeofday();

foreach (@incomingList) {
  my $inString = $_;
  &find_pattern($inString);
}

my $end = Time::HiRes::gettimeofday();
printf("%.6f\n", $end - $start);

查找模式方法:

sub find_pattern {
  my $URLString = $_[0];

  #1 rewrite
  if($URLString =~ m/^\/stuff\/brands-([^\/]*)\/(.*)?$/) {

  }
  #2 rewrite
  elsif($URLString =~ m/^\/coupons(\/.*)?$/){

  }
  #3 rewrite
  elsif($URLString =~ m/^\/han\/(.+)$/){

  }
  # ...continues on, there are 100 patterns. 
}

测试脚本.cpp: 主要方法:

populateArray();
//make stringArr, which contains all incoming strings
struct timeval time;
gettimeofday(&time, NULL);
double t1=time.tv_sec+(time.tv_usec/1000000.0);   

for(int j =0; j < 10000; j++){
  getRule(stringArr[j]);
 }

gettimeofday(&time, NULL);
double t2=time.tv_sec+(time.tv_usec/1000000.0);
printf("%.6lf seconds elapsed\n", t2-t1);

填充数组方法:

static void populateArray(){
regexArray[1] =  boost::regex ("\\/stuff\\/brands-([^\\/]*)\\/(.*)?");
regexArray[2] =  boost::regex ("\\/coupons(\\/.*)?");
regexArray[3] =  boost::regex ("\\/han\\/(.+)"); 
//continues on, 100 definitions. 
}

获取规则方法:

static void getRule(string inQuery){
  for(int i =1; i < 100; i++){
    if(boost::regex_match(inQuery, regexArray[i])){
      break; 
     }
  }

我知道我在 perl 中做 if else 检查的线性列表可能看起来有点奇怪,但那是因为我必须稍后单独重新格式化每个规则。无论如何,除非我误解了什么,否则这两个脚本非常相似 - 它们查找这个正则表达式定义列表直到找到匹配项,然后它们继续处理其他传入的字符串。

那么为什么这些结果如此不同呢? 对于 100 条规则(两个脚本都使用相同的规则)和 10,000 个输入, .cpp 平均约为 0.155 秒,而 .pl 平均约为 0.028 秒。 编辑:使用编译器优化后,C++ 脚本的运行时间约为 0.091 秒,仍然较慢。

任何见解都值得赞赏。

最佳答案

除了打开编译器优化设置外,尝试使用 boost::regex_constants::optimize 选项,它会指示正则表达式库构建最佳正则表达式状态机。

static void populateArray(){
regexArray[1] =  boost::regex ("\\/stuff\\/brands-([^\\/]*)\\/(.*)?", boost::regex_constants::optimize);
//continues on, 102 definitions. 
}

此外,请务必通过对 getRule 的引用而不是通过值来传递,因为您不希望堆分配的潜在开销。

如果您可以确保编译器内联该函数,那最好。

此外,正如 Oals 在上面评论的那样,您没有像在 Perl 中那样使用 C++ 正则表达式中的开始和结束行 anchor 。 ^...$

关于c++ - Perl 正则表达式运行速度快于 C++ Boost 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38084354/

相关文章:

Java模式匹配用于匹配特定模式

perl - 为什么在 Perl 中不推荐使用 Switch 模块?

perl - 如何使用Perl检查文件的扩展名?

C++ 编写一个函数,将 2 个 vector 的内容交织在一个 vector 中

c++ - 在 C++ 中将大数据读写到自定义二进制文件

c++ - 计算给定两组点的相似变换矩阵?

c# - 不同年份格式的正则表达式 c#

c++ - 如何在以指针作为参数的 header 中声明函数?

Java - 按正则表达式过滤列表条目

perl - CPAN 在 EC2/Linux AMI 上安装失败 : "Couldn' t untar"