衡量Java应用程序的性能

时间:2017-06-23 07:28:28

标签: java performance

我正在处理至少15年的申请。我正在努力改进具有大约10K代码行的特定流的性能。此流程涉及在JMS主题上向外部系统发送信息。在解决了我能够节省一些时间的问题之后,我在创建和缓存会话的过程中发现了一些问题。现在我想进一步提高性能。为此,我需要完成整个10K代码行,并确定我在哪里节省时间。这个流程分为三个部分 - Fist部分创建批量的单个请求并执行一些操作(大小为15的线程池) 第二部分从第一部分获取输入并进行更多处理(10个线程的线程池) 第三部分从第二部分获取输入并进行更多处理(10个线程的线程池)

我无法增加线程数量,因为资源有限,这不是应用程序中唯一的流程(我的配置是 - 2个套接字,每个套接字12个核心,每个核心2个线程)。此外,我没有太多的自由可以玩这个,因为这些第一,第二和第三部分也在其他地方使用。

要确定执行时间,我创建了一个包含一个包含日志语句的threadlocal变量的类,下面是代码:

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());
    }
}

在我的代码中,我只调用ExecutionTraceManager.addTrace,一旦线程完成任务,我调用printTrace并重置本地线程,以便下次此线程处理下一个请求时,它会看到空的跟踪列表。

这对我很好,但我想了解识别哪些代码花费时间的其他方法(因为我有~10行代码)。专业人士采取什么方法来处理这些问题。

2 个答案:

答案 0 :(得分: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飞行记录器中的分析器,尽管在生产环境中运行它需要付费许可证。 正如其他答案中提到的,还有其他工具,如VisualVM,可以使用分析器。

答案 1 :(得分:0)

使用JProfiler,简单易用。

通过它运行JAVA程序,测量各种功能的CPU使用率,内存使用情况,垃圾收集等。https://www.ej-technologies.com/products/jprofiler/overview.html