我正在使用一个简单的正则表达式来匹配从操作系统读取的具有以下格式的字符串:
时间戳:{逗号分隔的值列表}
其中时间戳是无符号的,值是无符号的
为此,我使用 boost::xpressive 使用以下正则表达式
std::vector< uint32_t > idleReports;
uint32_t timestamp = 0;
sregex cpuIdleVal = ( +_d )[ push_back( xp::ref( idleReports ), as<unsigned>( _ ) ) ];
sregex cpuIdleData = cpuIdleVal >> "," | cpuIdleVal;
sregex fullMatch = ( +_d )[ xp::ref( timestamp ) = as<unsigned>( _ ) ]
>> ":" >> +cpuIdleData;
smatch what;
if( regex_match( test, what, fullMatch ) )
{
// stuff
}
对于成功案例,一切正常,基准测试表明正则表达式需要大约 80 微秒来匹配以下字符串:
"1381152543:988900,987661,990529,987440,989041,987616,988185,988346,968859,988919,859559,988967,991040,988942"
如果输入字符串在其中一个值中包含负值,则性能会显着降低,因此如果 value4 为负,则正则表达式需要 13 秒来报告失败。
如果 value5 为负数,则花费的时间甚至更长。
为什么失败案例的性能如此糟糕?
我已通过将原始正则表达式更改为:
sregex cpuIdleData = "," >> cpuIdleVal;
sregex fullMatch = ( +_d )[ xp::ref( timestamp ) = as<unsigned>( _ ) ]
>> ":" >> cpuIdleVal >> -+ cpuIdleData ;
即对逗号分隔的列表进行匹配是非贪婪的。
在更改后的版本中,失败场景的表现与成功场景一样好(或略好于)。