python - regex.h 性能

标签 python c regex cython

我试图通过正则表达式匹配找出 Python、Cython 和纯 C 之间违反直觉的性能差异。

有一个小示例程序,它获取一个源文本文件 (17 KB),一个包含 2000 个单词的字典,用这些单词 (word1|word2|...) 创建一个正则表达式,并在中找到所述字典的所有实例源文件。

首先,我做了一个纯 Python 实现,如下所示:

def scanFile(filename, patterns):
   pattern_regex = re.compile('|'.join(patterns))
   pageContent = open(filename).read()
   matchingPatterns = set()
   for matchObj in pattern_regex.finditer(pageContent):
      matchingPatterns.add(matchObj.group(0))

   return matchingPatterns

然后,我尝试通过在 regex.h 而不是 Python 的 re 模块之上使用 Cython 重新实现相同的功能来优化它。

cdef extern from "regex.h" nogil:
   ctypedef struct regmatch_t:
      int rm_so
      int rm_eo
   ctypedef struct regex_t:
      pass
   int REG_EXTENDED
   int regcomp(regex_t* preg, const char* regex, int cflags)
   int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
   void regfree(regex_t* preg) 

def matchPatterns(bytes pageContent, bytes regex):
   cdef set matchingPatterns = set()
   cdef regex_t regex_obj
   cdef regmatch_t regmatch_obj[1]
   cdef int regex_res = 0
   cdef int current_str_pos = 0

   regcomp(&regex_obj, regex, REG_EXTENDED)
   regex_res = regexec(&regex_obj, pageContent[current_str_pos:], 1, regmatch_obj, 0)
   while regex_res == 0:
      matchingPatterns.add(pageContent[current_str_pos + regmatch_obj[0].rm_so: current_str_pos + regmatch_obj[0].rm_eo])
      current_str_pos += regmatch_obj[0].rm_eo
      regex_res = regexec(&regex_obj, pageContent[current_str_pos:], 1, regmatch_obj, 0)

   regfree(&regex_obj)
   return matchingPatterns

然而,性能却恰恰相反:Cython+regex.h 大约需要 2.34 秒,而 Python 需要 0.92 秒。

在运行了一些分析和自定义注释掉的代码后,我证实了它的怀疑是 regexec 每次调用需要 10 毫秒。

为了确保不是 Cython 出了问题,准备了一个独立的 C 单元测试,它使用相同的输入和 regex.h,它也显示出比 Python 更差的结果(大约 1.60 秒,即比 Python 慢 60%) .

因此,综上所述,如果您能深入了解为什么 regexec 性能如此差,我将不胜感激。

我在 Python 2.7.10、gcc 4.9.2、Cython 0.22 上运行它,平台是 Cygwin/Windows。在 Ubuntu 上运行时我也有类似的差异。

最佳答案

根据问题中的内容,我可以假设几个问题: - 你在 Windows 上使用 POSIX,而 Cygwin - 这是开销,Windows 不是 POSIX 系统。 -pcre(让我假设 pcre2)和 regex.h 之间有比较 -独立编译代码不同于导出函数(编译器不能假设任何东西) - 独立的 C 程序有很大的占用空间告诉你模式的重新编译或其他一些事情正在幕后发生。 - 编译选项和潜在的别名总是很难比较。

除了独立程序的源代码外,始终使用翻译器/转译器可能会产生延迟。 优化现在的任务是让您的编译器清楚地知道您在做什么并让它工作。

很抱歉,这部分与问题本身无关,但看起来您不需要 RE,而是需要基本的字符串匹配算法或一些简洁的结构(如前缀树和简单循环)来完成您的任务。

关于python - regex.h 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31067846/

相关文章:

python - Python 如何知道从我正在处理的代码中导入,而不是从站点包中导入?

.net - 用正则表达式匹配数字——只有数字和逗号

python - 使用正则表达式从文本文件中提取数字

php - 在 PHP 中用于 preg_replace 的分隔符(替换在 PHP 之外但不在 PHP 内部的工作)

python - 将 BaseHTTPServer 标准输出重定向到日志记录

python - 如何使用 python 制作现有列表中重复条目的另一个列表?

python - 可以用PyCharm Professional替代CLion-主要用于python

c - MacOS 上的 TensorFlow C 安装有问题? : dyld errors "Library not loaded: @rpath/libtensorflow.1.dylib" and "Symbol not found: __cg_DGifCloseFile"

c++ - 将 Arduino 库与 AVR-G++ 结合使用

c - 在C语言中读取文件时,文件是否需要与程序位于同一文件夹中?如果是这样,有什么方法可以读取另一个文件夹中的文件吗?