Boost Xpressive - почему случай сбоя этого регулярного выражения экспоненциальный?
Я использую простое регулярное выражение для сопоставления со строкой, прочитанной из ОС, которая имеет следующий формат:
отметка времени:{список значений через запятую}
Где отметка времени не подписана, значения не подписаны
Для этого я использовал следующее регулярное выражение, используя 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"
Если входная строка содержит отрицательное значение в одном из значений, производительность значительно ухудшается, так что если значение4 отрицательное, регулярному выражению требуется 13 секунд, чтобы сообщить об ошибке.
Если значение 5 является отрицательным, время, затрачиваемое еще
Почему производительность так плохо для случаев отказа?
Я исправил проблему, изменив исходное регулярное выражение на:
sregex cpuIdleData = "," >> cpuIdleVal;
sregex fullMatch = ( +_d )[ xp::ref( timestamp ) = as<unsigned>( _ ) ]
>> ":" >> cpuIdleVal >> -+ cpuIdleData ;
то есть сделать сравнение с разделенным запятыми списком не жадным.
В измененной версии сценарии сбоев работают так же хорошо (или немного лучше) сценариев успеха.