我与Linux C正则表达式库比较,
#include <iostream>
#include <chrono>
#include <regex.h>
int main()
{
const int count = 100000;
regex_t exp;
int rv = regcomp(&exp, R"_(([a-zA-Z][a-zA-Z0-9]*)://([^ /]+)(/[^ ]*)?)_", REG_EXTENDED);
if (rv != 0) {
std::cout << "regcomp failed with " << rv << std::endl;
}
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < count; i++)
{
regmatch_t match;
const char *sz = "http://www.abc.com";
if (regexec(&exp, sz, 1, &match, 0) == 0) {
// std::cout << sz << " matches characters " << match.rm_so << " - " << match.rm_eo << std::endl;
} else {
// std::cout << sz << " does not match" << std::endl;
}
}
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << elapsed.count() << std::endl;
return 0;
}
我的测试机器上的结果大约是60-70毫秒。
然后我使用了libc ++的库,
#include <iostream>
#include <chrono>
#include <regex>
int main()
{
const int count = 100000;
std::regex rgx(R"_(([a-zA-Z][a-zA-Z0-9]*)://([^ /]+)(/[^ ]*)?)_", std::regex_constants::extended);
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < count; i++)
{
std::cmatch match;
const char sz[] = "http://www.abc.com";
if (regex_search(sz, match, rgx)) {
} else {
}
}
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "regex_search: " << elapsed.count() << std::endl;
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < count; i++)
{
const char sz[] = "http://www.abc.com";
if (regex_match(sz, rgx)) {
} else {
}
}
end = std::chrono::high_resolution_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "regex_match: " << elapsed.count() << std::endl;
return 0;
}
regex_search&amp;的结果大约是2秒。 regex_match。这比C的regex.h库慢大约30倍。
我的比较有什么问题吗? C ++的正则表达式库不适用于高性能案例吗?
我可以理解它很慢,因为c ++的正则表达式库中没有优化,但是速度慢了30倍。
感谢。
大家好,
感谢您的回答。
对不起,我的错误是我也在使用[] C,但后来我改了,忘记更改C ++代码了。
我做了两处修改,
这仍然有点慢,但没有原始比较那么多。
答案 0 :(得分:11)
以下两行 not 做同样的事情!
const char sz1[] = "http://www.abc.com";
const char* sz2 = "http://www.abc.com";
这已经足以让它成为一个不公平的考验。
答案 1 :(得分:9)
如果您查看http://llvm.org/svn/llvm-project/libcxx/trunk/include/regex,您会看到此regex_match
的实现位于regex_search
之上,并且所有重载都会提取子表达式匹配位置,即使只是进入本地临时值扔掉了。 regex_search
使用vector
__state
个.resize()
调用它们的对象,因此大概也是向量 - 当子表达式匹配时不需要所有堆分配和不必要,但是需要跟踪在正则表达式的perl样式扩展中支持\1
等:旧的regcomp
/ regexec
C函数没有提供那些额外的功能工作。当然,如果clang实现检查了正则表达式在编译期间跟踪匹配的需要并调用更精简,更快的函数以便在可能的情况下匹配,那将是很好的,但我想他们只是从支持一般情况开始。
答案 2 :(得分:1)
sz
和match
是循环不变的,您应该将它们移到之前(在sz
的两种情况下)。
在第二种情况下,sz
是一个初始化数组而不是指向常量文字的指针 - 这是一种不公平且不必要的差异。也就是说,如果你按照建议将声明移到循环之前,那应该没什么区别。
虽然const regex_search()
的{{1}}重载可能会在内部造成const char*
的构建,但为了避免这种可能性,您应该使用以下方法对其进行测试:
std::string
(再次在循环之前)。
所以测试:
const std::string sz( "http://www.abc.com" ) ;
和
std::cmatch match;
const char* = "http://www.abc.com";
for (int i = 0; i < count; i++)
{
if (regex_search(sz, match, rgx)) {
} else {
}
}