4

次のコードは、メモリ使用量が多いためにしばらくするとクラッシュします(タスクマネージャを開くと、使用済みメモリが増え続けます)。しかし、ガベージコレクションがその役割を果たさないことを除いて、メモリリークは見られません。助言がありますか?

//Load a list of regex
//Load a list of phrases
//Open a output file

foreach (string regexString in regexList)
{
    int num = 0;

    Regex regex = new Regex(regexString, RegexOptions.Compiled | RegexOptions.IgnoreCase);

    foreach (string phrase in phraseList)
            num += regex.Matches(phrase).Count;

    if (num > 0)
    {
        output.WriteLine(String.Join(" ", num, phrase));
        output.Flush();
    }
}

編集:

完全なコード: http: //pastebin.com/0SQYn44z

EDIT2:

解決策を見つけて投稿しました(foreachループ)とにかく助けてくれたすべての人に感謝します。

4

5 に答える 5

6

あなたの例からはわかりませんが、RegexOptions.Compiledフラグが問題を引き起こしている可能性があります。msdnから:

Compiledは、正規表現がアセンブリにコンパイルされることを指定します。これにより、実行は高速になりますが、起動時間が長くなります。CompileToAssemblyメソッドを呼び出すときは、この値をOptionsプロパティに割り当てないでください。

正規表現がアセンブリにコンパイルされている場合、.Netはアセンブリをアンロードしないため、アプリケーションを再起動するまで、生成されたコードをアンロードできません。

つまり、さまざまな正規表現がたくさんあり、それらを再利用しない場合、コンパイルされた正規表現は通常はお勧めできません。

于 2012-06-24T01:58:10.277 に答える
2

正規表現が過度のバックトラッキングを使用しているため、実行時間が長くなり、メモリ使用量が多くなる可能性があります

確実に確認できるように、正規表現と入力を投稿できますか?

于 2012-06-24T01:54:59.063 に答える
1

あなたのコードを見た後、私はすでに2つではなく、1つの正規表現を組み合わせて使用​​することをお勧めします。何かのようなもの:

Regex regex = new Regex(
        @"\b(?:" + s1 + " " + s2 + "|" + s2 + " " + s1 + @")\b",
        RegexOptions.IgnoreCase);

そこでの一連の演算子は単一の呼び出し+に変換されることに注意してください。String.Concat(params string[])2〜4個のパーツしかないConcat場合、その場合にはより特殊なオーバーロードがあるため、一時配列を作成することすらできません。Join常に一時配列を使用し、空の場合でも区切り文字列を処理する必要があります。

もう1つ覚えておきたいのは、プログラムをデバッグモードで実行することは、リリースモードで実行することとはかなり異なるということです。たとえば、そのkeywordsリストは関数が戻るまで有効なままです。その存続期間を明示的に制限し、他のオブジェクトもできるだけ早くクリーンアップすることをお勧めします。たぶん次のようなものです:

string[] keywordArray;
using (StreamReader keywordsFile = new StreamReader("keywords.txt"))
{
    List<string> keywords = new List<string>();
    string keyword;
    while ((keyword = keywordsFile.ReadLine()) != null)
        keywords.Add(keyword);

    keywordArray = keywords.ToArray();
}

または、完全にスキップします。

string[] keywordArray = File.ReadAllLines("keywords.txt"); // internally uses above code

しかし、どういうわけか、巨大なフィードファイル全体をメモリにロードするのは悪い考えだと思います。一度に1つずつ逆シリアル化し、イテレータメソッドFeedItemから返すことができれば、必要なメモリははるかに少なくなります。次に、アルゴリズムを再構築して、フィード項目のループを最も外側のループにするだけです。

于 2012-06-24T07:11:18.473 に答える
1

これが正しいかどうか見てみましょう。キーワードの大きなリストがあり、それらの単語の 2 つの順列ごとに、それらを中間のスペースで結合して新しい文字列を作成し、さらに単語の順序を逆にした別の文字列を作成します (これは不要です、BTW) . 最後に、各文字列から Regex オブジェクトを作成します。

それが終わったら、FeedItem オブジェクトのリストを反復処理し始めます。それぞれの 2 つの属性を取得して、キーワードの場合と同様に文字列を形成し、その文字列を 2 つの正規表現のそれぞれと一致させようとします。要するに、当面は非難を控えて、コードのリファクタリングに集中するべきだと思います。実際、正規表現については今のところ忘れることをお勧めします。あなたは彼らの力をまったく使っておらず、彼らはあなたの本当の問題からあなたの気をそらしています.

于 2012-06-24T07:54:18.583 に答える
1

Dipose() を呼び出さずに IDisposable を実装するいくつかの型を使用します。

  • ストリームリーダー
  • StreamWriter
  • XmlReader

これらの型の使用を using ステートメントでラップし、それが改善されるかどうかを確認してください。

于 2012-06-24T02:41:29.880 に答える