2016-09-24 11 views
0

今日私はVisual VMのプロファイリングの結果に混乱しました。VisualVM - 奇妙な自己時間

public class Encoder { 
    ... 
    private BitString encode(InputStream in, Map<Character, BitString> table) 
     throws IOException { 

    BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 

    BitString result = new BitString(); 
    int i; 
    while ((i = reader.read()) != -1) { 
     char ch = (char) i; 
     BitString string = table.get(ch); 
     result = result.append(string); 
    } 

    return result; 
    } 
} 

このメソッドは、ストリームから文字を読み込み、一度に1:

は、私は次のような単純なJavaメソッドを持っています。各文字について、それはビット列表現を参照し、これらのビット列を結合してストリーム全体を表現します。

BitStringは、基本となるバイト配列を使用して一連のビットを表すカスタムデータ構造です。

このメソッドはパフォーマンスが非常に悪いです。問題はBitString#appendにあります。そのメソッドは新しいバイト配列を作成し、両方の入力BitStringからビットをコピーし、新しいBitStringインスタンスとして返します。私は何が起こっているかを確認するためにVisualVMのを使用しようとしたとき

public BitString append(BitString other) { 

    BitString result = new BitString(size + other.size); 
    int pos = 0; 

    for (byte b : this) { 
    result.set(pos, b); 
    pos++; 
    } 
    for (byte b : other) { 
    result.set(pos, b); 
    pos++; 
    } 

    return result; 
} 

しかし、ここで私が得たものです:

profiling

私は、一般的にはほとんどのVisual VMの経験とプロファイリングを持っています。私の理解では、これはencodeメソッド自体のどこかに嘘をついたかのように見えますが、appendにはありません。

確かに、私はこのように、計測カスタムタイムで全体のエンコード方法とアペンドコールを囲ん:

public class Encoder { 
    private BitString encode(InputStream in, Map<Character, BitString> table) 
     throws IOException { 

>> long startTime = System.currentTimeMillis(); 
>> long appendDuration = 0; 

    BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 

    BitString result = new BitString(); 
    int i; 
>> long count = 0; 
    while ((i = reader.read()) != -1) { 
     char ch = (char) i; 
     BitString string = table.get(ch); 

>> long appendStartTime = System.currentTimeMillis(); 
     result = result.append(string); 
>> long appendEndTime = System.currentTimeMillis(); 
>> appendDuration += appendEndTime - appendStartTime; 

>> count++; 
>> if (count % 1000 == 0) { 
>>  log.info(">>> CHARACTERS PROCESSED: " + count); 
>>  long endTime = System.currentTimeMillis(); 
>>  log.info(">>> TOTAL ENCODE DURATION: " + (endTime - startTime) + " ms"); 
>>  log.info(">>> TOTAL APPEND DURATION: " + appendDuration + " ms"); 
>> } 
    } 

    return result; 
    } 
} 

そして、私は次の結果得た:これは中にいるようだ

CHARACTERS PROCESSED: 102000 
TOTAL ENCODE DURATION: 188276 ms 
APPEND CALL DURATION: 188179 ms 

をVisual VMの結果と矛盾します。

私には何が欠けていますか?

+0

どのように時間を測定しましたか、そのコードを追加してください。 – hunter

+0

どのように時間が測定されたかの説明と、 'append'のコードを追加しました。私はIOやネットワークがそこに待っているとは思わない。 GCが一時停止する可能性はありますか? –

+0

[* this method *](http://stackoverflow.com/a/378024/23771)を試しましたか?それはJavaでうまく動作し、時間がどこに行くのかを正確に教えてくれます。注:*は測定しません。むしろ、アクティビティがそれを突き止めるのにかなりの時間を要するという事実を利用しています。それを使って非常に粗い測定値を得ることができますが、問題を正確に見つけ出します。 –

答えて

0

[この回答は無効です。この投稿には他の人が問題を理解するのに役立つ2つのコメントが含まれているので、OPからメンバーの助けを借りるまでそれを保ちます。

この場合、VisualVMは実際のCPU時間を測定しましたが、測定した時間値は「経過時間」です。

実行スレッドがIOまたはネットワークを待たなければならない場合、その時間はCPU時間として測定されません。

+0

私の拡張答えを見てください - 私は 'append'の実装を含んでいました。私はそこに行われたIOはないと思う。多分、GCは一時停止しますか?しかし、スクリーンショットで見ることができるように、Visual VMは2つの値、すなわち 'Time'と' Time(CPU) 'を表示します。 「経過時間」と「時間(CPU)」が「実際のCPU時間」ではないのですか? –

+0

はい、あなたは正しいです、何かここでは奇妙です、私の答えはあなたのケースでは有効ではありません。 2回のエンコード呼び出しでは、appendは4回しか呼び出されていません。一目ですべての呼び出しは記録されていません。 VisuvalVMをよく知っている人があなたを助けることができます。私はJProfilerに関する私の経験に基づいてあなたを助けようとしました。ありがとう – hunter

関連する問題