1

Stringを使用して生テキストのデータを読み取って処理するプログラムがありますStringTokenizer

もともとStringTokenizer約 1,500 のトークンが含まれており、プログラムは正常に動作します。ただし、生のコンテンツが増えて、現在は約 12,000 トークンになり、CPU 消費量が大幅に増加しています。

問題を調査し、根本原因を特定しようとしています。プログラムは while ループを使用してトークンが残っているかどうかを確認し、読み取ったトークンに基づいて別のアクションを実行します。これらのさまざまなアクションをチェックして、それらのアクションを改善できるかどうかを確認しています。

一方、1 つの長い長さを処理すると、10 の短いs StringTokenizerを処理する場合と比較して、より多くの CPU コストがかかるかどうかを尋ねたいと思います。StringTokenizer

4

3 に答える 3

1

まず、ご意見をお寄せいただきありがとうございます。先週末、修正したプログラムを使用して実際のデータでストレス テストを実行し、問題が解決してとても満足しています (AJ に感謝します ^_^ )。私の発見を共有したいと思います。

AJが言及した例を調べた後、StringTokenizerと「indexOf」を使用してデータを読み取って処理するテストプログラムを実行しました(私の状況では、正規表現はStringTokenizerと比較して最悪です)。私のテスト プログラムは、24 個のメッセージ (それぞれ ~12000 トークン) を処理するのに必要なミニ秒数をカウントします。

StringTokenizer は完了するのに最大 2700 ミリ秒かかりますが、"indexOf" は最大 210 ミリ秒しかかかりません!

次に、プログラムを次のように (最小限の変更で) 修正し、先週末に実際のボリュームでテストしました。

元のプログラム:

public class MsgProcessor {
    //Some other definition and methods ...

    public void processMessage (String msg) 
    {
        //...

        StringTokenizer token = new StringTokenizer(msg, FieldSeparator);
        while (token.hasMoreTokens()) {
            my_data = token.nextToken();
            // peformance different action base on token read
        }
    }
}

そして、「indexOf」を使用して更新されたプログラムは次のとおりです。

public class MsgProcessor {
    //Some other definition and methods ...
    private int tokenStart=0;
    private int tokenEnd=0;

    public void processMessage (String msg) 
    {
        //...
        tokenStart=0;
        tokenEnd=0;

        while (isReadingData) {
            my_data = getToken(msg);
            if (my_data == null)
                break;
            // peformance different action base on token read ...
        }
    }

    private String getToken (String msg)
    {
        String result = null;
        if ((tokenEnd = msg.indexOf(FieldSeparator, tokenStart)) >= 0) {
            result = msg.substring(tokenStart, tokenEnd);
            tokenStart = tokenEnd + 1;
        }
        return result;
    }
}
  • 元のトークンには「null」データがないことに注意してください。FieldSeparator が見つからない場合、"getToken(msg)" は null を返します ("no more token" のシグナルとして)。
于 2011-09-19T04:06:36.117 に答える
1

StringTokenizer Java docに従って、StringTokenizer の使用は推奨されません。非推奨ではありませんが、使用することは可能です。推奨されないだけです。書かれている内容は次のとおりです。

「StringTokenizer は、新しいコードでの使用は推奨されていませんが、互換性のために保持されている従来のクラスです。この機能を求める人は、代わりに String の split メソッドまたは java.util.regex パッケージを使用することをお勧めします。」

以下の投稿をご確認ください。あなたがやろうとしているのと同じことをするためのさまざまな方法の非常に良い例があります.

パフォーマンスオブストリングトークンナイザークラス vs 分割メソッド in Java

そこで提供されているサンプルを試して、何が最適かを確認してください。

于 2011-09-14T10:50:43.927 に答える
0

代わりに、新しい Scanner クラスを試してみませんか? スキャナーは、ストリームとファイルを使用して構築できます。ただし、古い StringTokenizer よりも効率的かどうかはわかりません。

于 2011-09-14T10:41:12.283 に答える