C linux 正则表达式性能问题
C linux regex performance issue
我正在创建一个逐行读取文件的程序,将该行与正则表达式匹配并显示与该正则表达式匹配的行数。问题是,这个程序使用了相当大的 CPU 百分比。 67.5%
没有 valgrind 和有 valgrind 100.1%
并且它非常慢 ~5 seconds for 84000 lines
。 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(®ex,"^(\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(®ex, line, 0, NULL, 0)) {
// printf("Match\n");
regfree(®ex);
return 1;
}
else{
// printf("No Match\n");
regfree(®ex);
return 0;
}
}
首先,如果某些东西的使用率低于 100% cpu,这意味着瓶颈是 I/O 或其他东西,而不是 cpu。
话虽这么说。您为每次调用 check_regex
函数重新编译正则表达式。这看起来效率很低。正则表达式匹配以这种方式拆分的原因是因为正则表达式的编译速度可能非常慢。您应该编译一次正则表达式,然后根据需要多次重复使用它。
我正在创建一个逐行读取文件的程序,将该行与正则表达式匹配并显示与该正则表达式匹配的行数。问题是,这个程序使用了相当大的 CPU 百分比。 67.5%
没有 valgrind 和有 valgrind 100.1%
并且它非常慢 ~5 seconds for 84000 lines
。 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(®ex,"^(\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(®ex, line, 0, NULL, 0)) {
// printf("Match\n");
regfree(®ex);
return 1;
}
else{
// printf("No Match\n");
regfree(®ex);
return 0;
}
}
首先,如果某些东西的使用率低于 100% cpu,这意味着瓶颈是 I/O 或其他东西,而不是 cpu。
话虽这么说。您为每次调用 check_regex
函数重新编译正则表达式。这看起来效率很低。正则表达式匹配以这种方式拆分的原因是因为正则表达式的编译速度可能非常慢。您应该编译一次正则表达式,然后根据需要多次重复使用它。