0

探している文字列が含まれている場合と含まれていない場合がある可変長のログファイルがあります。

行にはタイムスタンプなどがあり、その後に<parameter>#<value>が続きます。パラメーターを確認して値を抽出したいと思います。

以下の実装は機能しますが、ファイルを解析するためのより効率的な方法が必要であると確信しています。

キーポイント:

  • ほとんどの行は無視されます
  • 1〜20Mbの約1600のログファイルがあります
  • ファイルあたりのわずかなゲインでも利点があります

NB。解析関数は部分文字列を呼び出し、それをintに変換します

どんなアイデアでも大歓迎

ifstream fileReader(logfile.c_str());
string lineIn;
if(fileReader.is_open())
{

while(fileReader.good())
{
    getline(fileReader,lineIn);

    if(lineIn.find("value1#") != string::npos)
    {
        parseValue1(lineIn);
    }
    else if(lineIn.find("value2#") != string::npos)
    {
        parseValue2(lineIn);
    }
    else if(lineIn.find("value3#") != string::npos)
    {
        parseValue3(lineIn);
    }   
}
}
fileReader.close();
4

4 に答える 4

1

まず第一に、あなたはループを間違ってやっています。コードは次のようになります。

while( getline( fileReader,lineIn ) ) {
}

第二に、行:

if( fileReader.is_open() )

fileReader.close();

冗長です。スピードも。正規表現を使用することをお勧めします:

std::regex reg ( "(value1#)|(value#2)|(value#3)(\\d+)" );
while( getline( fileReader,lineIn ) ) {
    std::smatch m;
    if( std::regex_search( lineIn.begin(), lineIn.end(), m, reg ) ) {
        std::cout << "found: " << m[4] << std::endl;
    } 
}

もちろん、それに応じて正規表現を変更する必要があります。

残念ながら、iostreamはかなり遅いことが知られています。十分なパフォーマンスが得られない場合は、fstreamをFILE*またはmmapに置き換えることを検討してください。

于 2013-03-06T17:28:58.063 に答える
0

同じ文字列で何度も検索が繰り返されているように見えますが、これはあまり効率的ではありません。

ファイル/行を適切な方法で解析します。

Boostには、役立つ可能性のある3つのライブラリがあります。

正規表現を使用して行を解析します: http ://www.boost.org/doc/libs/1_53_0/libs/regex/doc/html/index.html

トークナイザーを使用する http://www.boost.org/doc/libs/1_53_0/libs/tokenizer/index.html

完全にカスタマイズするには、いつでもSpiritを使用できます。 http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/index.html

于 2013-03-06T17:19:32.293 に答える
0

最初のステップは、に費やされた時間とif(lineIn.find(...)...、入力ファイルの実際の読み取り量を把握することです。

アプリケーションの実行時間(すべてではなく、選択したログファイルを取得することをお勧めします)。これを数回続けて実行して、同じ(ほぼ)値が得られることを確認することをお勧めします。

追加:

#if 0
if (lineIn.find(...) ...) 
...
#endif

かかる時間を比較します。私の推測では、それは実際にはそれほど大きな違いにはならないでしょう。ただし、検索が時間の主要な要素である場合は、より巧妙な検索方法を使用することが有益であることがわかる場合があります。より大きな文字列内の文字列を検索するための非常に巧妙な方法がいくつかあります。

他の場所に投稿した「ファイルをより速く読む」というベンチマークをいくつか付けて投稿します。ただし、読み取り元のハードディスクが主要な時間になることに注意してください。

参照:

ファイルを読み取っているときのgetlineと、ファイル全体を読み取ってから改行文字に基づいて分割するときのgetline

少し関連性は低いですが、おそらく興味深いものです。

C++でテキストファイルから行で区切られた何百万もの整数を読み取るための最も効率的な方法は何ですか

于 2013-03-06T17:20:50.080 に答える
0

実行のボトルネックはファイルI/Oにあります。
1回のフェッチでできるだけ多くのデータをバッファに取り込むことをお勧めします。次に、バッファでトークンを検索します。

あなたはそれを検索するためにテキストを読まなければならないので、あなたはできるだけ多くのファイルを読んだほうがよいでしょう。

あまりにも多くのデータをメモリに読み込むことには、いくつかの欠点があるかもしれません。OSがすべてのデータを収めることができない場合は、ハードドライブにページアウトする可能性があります。これにより、この手法は無意味になります(OSにファイルのチャンク読み取りを処理させない場合)。

ファイルがメモリに格納されると、検索手法によるパフォーマンスの向上はごくわずかになる可能性があります。

于 2013-03-06T19:22:06.603 に答える