为什么 pcre regex 比 c++11 regex 快得多
Why pcre regex is much faster than c++11 regex
一些示例代码。这是使用 cregex_iterator:
的 c++11 部分
std::chrono::steady_clock::time_point begin0 = std::chrono::steady_clock::now();
regex re("<option[\s]value[\s]*=[\s]*\"([^\">]*)\"[\s]*[^>]*>", regex::icase);
int found = 0;
for (std::cregex_iterator i = std::cregex_iterator(input, input + input_length, re);
i != std::cregex_iterator();
++i)
{
found++;
if (found < 10000) continue;
break;
}
std::chrono::steady_clock::time_point end0 = std::chrono::steady_clock::now();
这是pcre部分。正则表达式都是一样的。
std::chrono::steady_clock::time_point begin4 = std::chrono::steady_clock::now();
const char *pError = NULL;
int errOffset;
int options = PCRE_MULTILINE | PCRE_CASELESS;
const char* regexp = "<option[\s]value[\s]*=[\s]*\"([^\">]*)\"[\s]*[^>]*>";
pcre* pPcre = pcre_compile(regexp, options, &pError, &errOffset, 0);
int offset = 0;
int matches = -1;
int pMatches[6];
while (offset < input_length)
{
matches = pcre_exec(pPcre,NULL, input, input_length, offset,0, pMatches,6);
if (matches >= 1)
{
found++;
offset = pMatches[1];
if (found < 10000) continue;
break; // find match
}
else
offset = input_length;
}
std::chrono::steady_clock::time_point end4 = std::chrono::steady_clock::now();
结果显示pcre比c++11快100倍。我在 C++11 实现中发现了一些矢量复制和调整大小。还有其他原因吗?
PCRE 受益于一些称为 启动优化 的优化,这些优化配置为默认启用。这些优化包括:
- 未锚定模式的主题预扫描(如果 starting 点是
未找到引擎甚至懒得去匹配
过程。)
- 研究模式以确保主题的最小长度不短于模式本身
- 自动拥有
- 快速失败(如果具体点是
未找到引擎甚至懒得去匹配
过程。)
表面形态分析:
<option # Subject pre-scan applied (unachored pattern)
[\s]
value
[\s]* # Auto-possessification applied (translates to \s*+)
=
[\s]* # //
\"([^\">]*)\"
[\s]* # //
[^>]*
> # Min length (17 chars) check of subject string applied
此外,如果输入字符串没有像 >
这样的特殊字符,则应该抛出快速失败。您应该知道,性能在很大程度上也取决于输入字符串。
运行 下面的模式:
(*NO_AUTO_POSSESS)(*NO_START_OPT)<option[\s]value[\s]*=[\s]*\"([^\">]*)\"[\s]*[^>]*>
在此输入字符串上(观看那段时间):
<option value .
并比较结果 (Live demo)。
一些示例代码。这是使用 cregex_iterator:
的 c++11 部分std::chrono::steady_clock::time_point begin0 = std::chrono::steady_clock::now();
regex re("<option[\s]value[\s]*=[\s]*\"([^\">]*)\"[\s]*[^>]*>", regex::icase);
int found = 0;
for (std::cregex_iterator i = std::cregex_iterator(input, input + input_length, re);
i != std::cregex_iterator();
++i)
{
found++;
if (found < 10000) continue;
break;
}
std::chrono::steady_clock::time_point end0 = std::chrono::steady_clock::now();
这是pcre部分。正则表达式都是一样的。
std::chrono::steady_clock::time_point begin4 = std::chrono::steady_clock::now();
const char *pError = NULL;
int errOffset;
int options = PCRE_MULTILINE | PCRE_CASELESS;
const char* regexp = "<option[\s]value[\s]*=[\s]*\"([^\">]*)\"[\s]*[^>]*>";
pcre* pPcre = pcre_compile(regexp, options, &pError, &errOffset, 0);
int offset = 0;
int matches = -1;
int pMatches[6];
while (offset < input_length)
{
matches = pcre_exec(pPcre,NULL, input, input_length, offset,0, pMatches,6);
if (matches >= 1)
{
found++;
offset = pMatches[1];
if (found < 10000) continue;
break; // find match
}
else
offset = input_length;
}
std::chrono::steady_clock::time_point end4 = std::chrono::steady_clock::now();
结果显示pcre比c++11快100倍。我在 C++11 实现中发现了一些矢量复制和调整大小。还有其他原因吗?
PCRE 受益于一些称为 启动优化 的优化,这些优化配置为默认启用。这些优化包括:
- 未锚定模式的主题预扫描(如果 starting 点是 未找到引擎甚至懒得去匹配 过程。)
- 研究模式以确保主题的最小长度不短于模式本身
- 自动拥有
- 快速失败(如果具体点是 未找到引擎甚至懒得去匹配 过程。)
表面形态分析:
<option # Subject pre-scan applied (unachored pattern)
[\s]
value
[\s]* # Auto-possessification applied (translates to \s*+)
=
[\s]* # //
\"([^\">]*)\"
[\s]* # //
[^>]*
> # Min length (17 chars) check of subject string applied
此外,如果输入字符串没有像 >
这样的特殊字符,则应该抛出快速失败。您应该知道,性能在很大程度上也取决于输入字符串。
运行 下面的模式:
(*NO_AUTO_POSSESS)(*NO_START_OPT)<option[\s]value[\s]*=[\s]*\"([^\">]*)\"[\s]*[^>]*>
在此输入字符串上(观看那段时间):
<option value .
并比较结果 (Live demo)。