gpt4 book ai didi

python - regex.h 性能

转载 作者:太空狗 更新时间:2023-10-30 01:33:37 26 4
gpt4 key购买 nike

我试图通过正则表达式匹配找出 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com