可能是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胜制,而不是统计差异测试。
这是你的代码,而不是语言。
- 将函数作为
std::function
传递会使C++代码变慢 - 在每次迭代中调用时钟函数
- 创建新对象,例如
std::smatch
匹配;在每次迭代中 - 运行功能
- 未预编译正则表达式
我还想知道您运行的优化是什么。
run()
函数做得太多了。修复。:)