C语言Linux环境下正则表达式性能问题

3
我正在创建一个程序,逐行读取文件,匹配该行的正则表达式,并显示有多少行与该正则表达式匹配。问题是,这个程序使用了相当大比例的 CPU:67.5%,而使用valgrind后则为 100.1%,速度非常慢,在处理84000行数据时需要~5秒钟。而且 valgrind 输出的如下(输入文件共 84000 行)。
为什么会使用这么多 CPU?为什么会这么慢?是否有任何方法可以使其更快并减少内存和 CPU 的使用率?谢谢。
==10737== HEAP SUMMARY:
==10737==     in use at exit: 0 bytes in 0 blocks
==10737==   total heap usage: 42,200,387 allocs, 42,200,387 frees, 5,441,088,516 bytes allocated
==10737== 
==10737== All heap blocks were freed -- no leaks are possible
==10737== 
==10737== For counts of detected and suppressed errors, rerun with: -v
==10737== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

源代码:

#include <stdio.h>
#include "stdlib.h"
#include <string.h>
#include <regex.h>

int check_regex(char* line);
void regex_test(const char* log_file);

int main(){
    regex_test("/var/log/syslog");
}

void regex_test(const char* log_file){
    printf("%s\n", log_file);
   FILE * fp;
   char * line = NULL;
   size_t len = 0;
   ssize_t read;
   int line_count=0;
   int match_count=0;
   fp = fopen(log_file, "r");
   if (fp == NULL)
       exit(EXIT_FAILURE);

   while ((read = getline(&line, &len, fp)) != -1) {
    // printf("%p\n", &line);
    if (check_regex(line))
    {
      match_count++;
    }else{
      printf("%s", line);
      printf("%d\n", line_count);
      // exit(0);
    }
    line_count++;
   }
   printf("%d/%d\n",match_count, line_count);
   fclose(fp);
   if (line)
       free(line);
}

int check_regex(char* line){
  regex_t regex;
  if (regcomp(&regex,"^(\\w+[ ]+[0-9]+ [0-9]+:[0-9]+:[0-9]+) [A-Za-z0-9-]+ [A-Za-z\\/]+\\[?[^]:]*\\]?: <?(\\w+)?>? ?(.+)$", REG_EXTENDED)) {
      printf("Could not compile regex\n");
      exit(1);
  }
  if (!regexec(&regex, line, 0, NULL, 0)) {
      // printf("Match\n");
      regfree(&regex);
      return 1;
  }
  else{
      // printf("No Match\n");
      regfree(&regex);
      return 0;
  }
}

2
你应该只创建一个正则表达式对象,但现在每次发送一行进行检查时,它都会重新创建。将“regcomp”移动到“check_regex”之外,我认为你的性能会好得多。 - Wiktor Stribiżew
是的 - 就像 @stribizhev 说的那样。虽然这在 C 中很不寻常 - 通常是 C++ 开发人员坚持不断地创建和销毁复杂的结构体/对象/子系统 :) - Martin James
1个回答

4

首先,如果某个东西使用的CPU不到100%,则意味着瓶颈是I/O或其他因素,而不是CPU。

话虽如此,每次调用check_regex函数都会重新编译正则表达式。这看起来非常低效。将正则表达式匹配分拆的原因是因为编译正则表达式可能相当慢。您应该编译一次正则表达式,然后根据需要重复使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接