次の形式を持つOSから読み取った文字列と照合するために、単純な正規表現を使用しています。
タイムスタンプ:{コンマ区切りの値のリスト}
タイムスタンプが符号なしの場合、値は符号なしです
これを行うには、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
}
成功した場合はすべて正常に機能します。ベンチマークでは、正規表現が次の文字列と一致するのに約 80usec かかることが示されています。
"1381152543:988900,987661,990529,987440,989041,987616,988185,988346,968859,988919,859559,988967,991040,988942"
入力文字列のいずれかの値に負の値が含まれていると、パフォーマンスが大幅に低下します。値 4 が負の場合、正規表現が失敗を報告するのに 13 秒かかります。
value5 が負の場合、所要時間はさらに長くなります。
失敗した場合のパフォーマンスが非常に悪いのはなぜですか?
元の正規表現を次のように変更して問題を修正しました。
sregex cpuIdleData = "," >> cpuIdleVal;
sregex fullMatch = ( +_d )[ xp::ref( timestamp ) = as<unsigned>( _ ) ]
>> ":" >> cpuIdleVal >> -+ cpuIdleData ;
つまり、コンマ区切りのリストに対して非貪欲な一致を作成します。
変更されたバージョンでは、失敗のシナリオは成功のシナリオと同じくらい (またはわずかに優れています) 実行されます。