Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python regex.h性能_Python_C_Regex_Cython - Fatal编程技术网

Python regex.h性能

Python regex.h性能,python,c,regex,cython,Python,C,Regex,Cython,我试图找出Python、Cython和使用正则表达式匹配的纯C之间违反直觉的性能差异 有一个小的示例程序,它获取一个源文本文件(17KB),一个包含2000个单词的字典,用这些单词(word1 | word2 |……)创建一个正则表达式,并在源文件中查找所述字典的所有实例 首先,我完成了一个纯Python实现,如下所示: def scanFile(filename, patterns): pattern_regex = re.compile('|'.join(patterns)) p

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

有一个小的示例程序,它获取一个源文本文件(17KB),一个包含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秒

在运行了一些评测和自定义注释代码之后,我确认了这一怀疑,即每次调用都需要10毫秒的时间
regexec

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

因此,有了所有这些,我非常感谢能够深入了解为什么
regexec
的性能如此糟糕


我在Python2.7.10、GCC4.9.2、Cython0.22上运行它,平台是Cygwin/Windows。在Ubuntu上运行同样的程序时,我也遇到了类似的问题。

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

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


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

您有独立C单元测试的代码吗?为什么您会认为C的正则表达式引擎比各种Python实现中使用的要快?它们都可能以本机C代码的形式运行,并且在实现正则表达式引擎时可能会有很多变体。在得出性能结论之前,您可能需要更大范围的REs。您可能已经在一个RE引擎中发现了一个弱点,但却忽略了它的优点,因为您只是在尝试OR。可能涉及其他代码,例如,您在Python中使用的是
set()
,您在C中也这样做了吗?BRE/ERE的一个可能实现是在回溯引擎的顶部实现它,而不是在最后使用accept节点,它跟踪最长的比赛,让引擎继续尝试,直到用尽所有可能。结果,这样的实现比回溯引擎完成了更多的工作。至于这样做的原因——因为BRE支持回溯引用,所以无论如何都有必要实现回溯引擎。他们可能不费心为没有反向引用的模式包括一个有效的实现。@放松-主要是因为python
re
的性能比boost::regex差得多。因为我想试用Cython(学习体验和优化),所以我去了ReXEX。h,因为它是纯C。我意识到在Cython中可以包含C++和增强:ReGEX和ReEX.H不是天生平等的,但我希望在这两个方面都能获得类似的收益。这种差异引发了这个问题@cdarke——事实上,大型ORs模式很可能是Python能够更好地处理的事情。但是从regex.h文档中不清楚它是否能够很好地处理它。