2017-06-23 15 views
0

私は少なくとも15歳のアプリケーションで作業しています。私は約10K行のコードを持つ特定のフローのパフォーマンスを改善するために取り組んでいます。このフローでは、JMSトピックで外部システムに情報を送信します。いくつかの時間を節約できた問題を解決してセッションを作成したりキャッシュしたりする方法で私が特定した問題がありました。今私はさらにパフォーマンスを向上させたい。このためには、10K行のコード全体を調べ、どこに保存時間の範囲があるかを判断する必要があります。 フィストパートは個々のリクエストのバッチを作成し、いくつかの操作を実行します(サイズ15のスレッドプール) 2番目のパートは最初のパートから入力を受け取り、さらに処理します(10スレッドのスレッドプール) 3番目のパートJavaアプリケーションのパフォーマンスを測定

スレッド数を増やすことはできません。リソースが限られているため、これはアプリケーション内の唯一のフローではありません(私の設定は-2ソケットです。これは2つのソケットからの入力を受け取り、ソケットあたり12コア、コアあたり2スレッド)。また、これらの第1、第2、第3の部分は他の場所でも使用されているので、私はこれで遊ぶ自由はあまりありません。スレッドが完了すると、私はちょうどExecutionTraceManager.addTraceを呼び出すと、私のコードで

public class ExecutionTraceManager { 

private static Category cat = Category.getInstance(ExecutionTraceManager.class.getCanonicalName()); 

private static final ThreadLocal<Tracer> traceContainer = new ThreadLocal<Tracer>() { 
    @Override 
    protected Tracer initialValue() { 
     return new ExecutionTraceManager().new Tracer(); 
    } 
}; 

public static void addTrace(String trace) { 
    traceContainer.get().addTrace(trace); 
} 

public static void printTrace(){ 
    ArrayList<String> trace = traceContainer.get().trace; 
    StringBuffer buffer = new StringBuffer(); 
    for(String current : trace){ 
     buffer.append(current).append("\n"); 
    } 

    cat.info(buffer); 
} 

public class Tracer { 
    ArrayList<String> trace = new ArrayList<String>(); 
    long startTime = System.nanoTime(); 
    boolean init = false; 
    public void addTrace(String traceMessage) { 
     if(!init){ 
      startTime = System.nanoTime(); 
      init = true; 
     } 
     StringBuffer buffer = new StringBuffer("Time taken till [ ") 
       .append(traceMessage) 
       .append(" ] is : " 
         + ((System.nanoTime() - startTime)/1000000.0)); 
     trace.add(buffer.toString()); 
    } 
} 

は、私は、ロギング・ステートメントが含まれている1つのThreadLocal変数を持つクラスを作成した実行時間を決定するには、以下のコードでありますタスク私はprintTraceを呼び出し、スレッドのローカルをリセットするので、このスレッドが次の要求を処理する次回には空のトレースリストが表示されます。

これは私には問題ありませんが、コードが10行あるので、どのコードが時間を費やしているかを識別する他の方法は何ですか?そのような問題を処理するためにどのようなアプローチが取られているか

+4

プロファイラを使用します。たとえばVisualVM https://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/profiler.html –

+0

yourkitのようなプロファイラを使用して壁の時間を測定します。 – Rnet

+0

Stephen C、JVisualVMがお手伝いしてくれてありがとう –

答えて

1

Metricsのようなメトリクス収集ライブラリを使用してメトリックの収集ライブラリに

を使用し、それはサンプリングを扱うと様々なメトリックの実装(タイマー、ヒストグラムなど)を持っているので、私の意見では、あなた自身の圧延より良いソリューションです。 基本的に、あなたは、このようなコードを追加します。

private final Timer responses = metrics.timer(name(RequestHandler.class, "responses")); 

// in the method 
    try (Timer.Context ctx = responses.time()) { 
     // run operations 
    } 
} 

これは、さまざまなパーセンタイル(99、95、90、など)を照会することができます実行時間のヒストグラムを生成します。 また、運用システムで実行してメトリックを収集できるという利点もあります。

プロファイラーは、アプリケーションが行うものにマッピングするのが難しい非常に高密度の出力を生成する傾向があるため、このアプローチはプロファイラーよりも好まれます。 アプリケーションレベルのタイミングメトリックは、理解しやすく、処理しやすいメトリックを生成します。

は、本番環境でそれを実行すると、支払ったライセンスが必要ですが、あなたはまた、Mission Controlのフライトレコーダー内の1つのようにプロファイラを使用することができますプロファイラ

を使用してください。 他の回答でも触れたように、VisualVMのようなツールがあり、使用できるプロファイラがあります。

関連する問題