Regex速度:Python在VS2013下比C++11快x6倍



可能是python的C regex实现速度快了6倍,还是我遗漏了什么?

Python版本:

import re
r=re.compile(r'(HELLO).+?(d+)', re.I)
s=r"prefixdfadfadf adf adf adf adf he asdf dHello Regex 123"
%timeit r.search(s)
1000000 loops, best of 3: 1.3 µs per loop (769,000 per sec)

C++11版本:

#include<regex>
int main(int argc, char * argv[])
{
std::string s = "prefixdfadfadf adf adf adf adf he asdf dHello Regex 123";
std::regex my(R"((HELLO).+?(d+))", regex_constants::icase);
bench_utils::run(std::chrono::seconds(10),
[&]{
std::smatch match;
bool found = std::regex_search(s, match, my);
});       
return 0;
}
Results in about ~125,000 searches/second

编辑:这是bench_utils:的代码

namespace bench_utils
{
template<typename T>    
inline std::string formatNum(const T& value)
{
static std::locale loc("");
std::stringstream ss;
ss.imbue(loc);
ss << value;
return ss.str();
}
inline void run(const std::chrono::milliseconds &duration,
const std::function<void() >& fn)
{
using namespace std::chrono;
typedef steady_clock the_clock;
size_t counter = 0;
seconds printInterval(1);
auto startTime = the_clock::now();
auto lastPrintTime = startTime;
while (true)
{
fn();
counter++;
auto now = the_clock::now();
if (now - startTime >= duration)
break;
auto p = now - lastPrintTime;
if (now - lastPrintTime >= printInterval)
{
std::cout << formatNum<size_t>(counter) << " ops per second" << std::endl;
counter = 0;
lastPrintTime = the_clock::now();
}
}
}
}

首先要注意的是,在Python中,regex(无论是使用re还是regex模块)都以"c的速度"发生,也就是说,实际的重载代码是冷硬c,因此至少对于较长的字符串,性能将取决于c regexp实现。

有时python非常聪明,python在每秒数千万次操作附近执行时没有问题,每秒可以创建数百万个对象——这比c慢一千倍,但如果我们谈论的是一开始需要微秒的事情,python开销可能并不重要,它只会给每个函数调用增加0.1微秒。

因此,在这种情况下,Python的相对较慢并不重要。它的绝对速度足够快,重要的是正则表达式函数执行任务的速度。

我重写了c++的情况,使其不受任何批评(我希望,可以随意指出任何批评),事实上,它甚至不需要创建匹配对象,因为搜索只返回一个bool(true/false):

#include <regex>
#include <iostream>
int main(int argc, char * argv[])
{
std::string s = "prefixdfadfadf adf adf adf adf he asdf dHello Regex 123";
std::regex my(R"((HELLO).+?(d+))", std::regex_constants::icase);
int matches = 0;
for (int i = 0; i < 1000000; ++i)
matches += std::regex_search(s, my);

std::cout << matches  << std::endl;
return 0;
}

我写了一个类似的python程序(尽管python确实创建并返回了一个匹配对象),我的结果与您的完全相同

c++:6.661spython:1.039s

我认为这里的基本结论是python的regex实现简单地击败了c++标准库。

它也会颠簸Go

不久前,为了好玩,我比较了Python的regex性能和Go的regex的性能。蟒蛇的速度至少是它的两倍。

结论是python的regexp实现非常好,您当然不应该将目光投向python之外以获得改进的regexp性能。正则表达式所做的工作基本上足够耗时,以至于Python的开销根本无关紧要,而且Python有一个很好的实现(新的regex模块通常比re更快)。

使用timeit进行基准测试是错误的,因为它提供了3胜制,而不是统计差异测试。

这是你的代码,而不是语言。

  1. 将函数作为std::function传递会使C++代码变慢
  2. 在每次迭代中调用时钟函数
  3. 创建新对象,例如std::smatch匹配;在每次迭代中
  4. 运行功能
  5. 未预编译正则表达式

我还想知道您运行的优化是什么。

run()函数做得太多了。修复。:)

最新更新