Use Java profiler to optimize code performance and solve OOM problems

Sometimes the blog content will change. The first blog is the latest, and other blog addresses may not be synchronized. Check it carefully.https://blog.zysicyj.top

First blog address


background

Recently I have been doing performance optimization on a stand-alone application. It mainly involves business related to analysis, import and export.

Let’s briefly talk about what this stand-alone application is for: making ticket samples, similar to answer sheets. Send it to some people to fill in, then save it into the database through stand-alone Python image recognition, and conduct various analyzes and summarize the data on our stand-alone platform.

Two parts have been optimized previously, one is analysis (the current performance has been improved by 8 times, and will be optimized in the future), and the other is summary (the performance has been improved by 10 times +, and will be optimized in the future).

I write this because there is a service that always OOMs when there is a large amount of data. It is really a headache. I can only do memory analysis. There are many major software for memory analysis. . I won’t bother here, just use the one that comes with Idea. I personally think it is invincible in the universe.

In actual business, we need to implement a function, one-click machine replacement. My implementation idea is to export the sql file and then import the sql file on another machine.

The amount of data here is really too large, mainly because the picture data is too large. Because of the history table design problem, the pictures are stored directly in the database.

We work in batches as a group. There are multiple units under one batch. There may be thousands of pieces of data under one unit. Each piece of data has a picture. Most of the pictures are about 200k in size.

Another limitation is that the actual single-machine memory for running the program is only 4g, which is very small.

The amount of data exported by one unit is probably more than 2 gigabytes.

how to use

There is an analyzer under View > Tool Window, click on it

If your idea does not have this function, please upgrade to the latest version

alt

Then we start the project normally

After the project is started, the started process will be flashed here, and then we need to attach the Profile

alt

If it shows that it is being analyzed, then there is no problem. Let’s go to the website to perform the export operation.

alt

View CPU and heap memory in real time

You can see this situation here because I optimized it and manually GC after each processing. If you don't do manual GC, it will be OOM after about three rounds of processing.

This is also a method that I have optimized. In the future, I plan to increase the threshold for each batch processing to improve the efficiency of single processing.

alt

When we click to stop the analysis, we will see the following page

Analyze results

flame graph

火焰图(Flame graph)是一种可视化工具,用于分析和优化软件的性能。它以图形的形式展示了程序在执行过程中各个函数的调用关系和耗时情况。

火焰图的横轴表示程序的执行时间,纵轴表示函数调用栈。每个函数在火焰图中以一个矩形表示,矩形的宽度表示函数在执行过程中所占用的时间比例,矩形的高度表示函数的调用深度。通过火焰图,我们可以直观地看到程序中哪些函数占用了大量的时间,从而帮助我们找到性能瓶颈和优化的方向。

要生成火焰图,通常需要使用性能分析工具来采集程序的执行数据。常用的性能分析工具包括Linux下的perf、Java应用程序中的Java Flight Recorder(JFR)和Java VisualVM等。这些工具可以记录程序的函数调用信息和耗时情况,并生成火焰图。

生成火焰图后,我们可以通过观察火焰图中的热点函数(即占用时间较多的函数)来进行性能优化。可以考虑对热点函数进行代码优化、算法优化、并发优化等,以提高程序的性能和响应速度。

alt

调用树

调用树(Call Tree)是一种可视化工具,用于展示程序在执行过程中函数之间的调用关系。它以树状结构的形式展示了函数的调用层次和调用次数。 在调用树中,根节点表示程序的入口函数,每个子节点表示一个被调用的函数。通过观察调用树,我们可以了解函数之间的调用流程,找到函数的调用路径和调用次数,从而帮助我们分析程序的执行逻辑和性能瓶颈。 调用树通常会显示每个函数的调用次数和总耗时。这样我们可以快速识别出调用次数较多或耗时较长的函数,从而找到可能的性能问题和优化的方向。

alt

方法列表

alt

时间线

alt

事件

alt

分析

这些图吧,看着也不麻烦,揣摩下也大概能知道干嘛的,我举个例子

在调用树视图中,我们一直点下去,看到下面这个方法,占用了33.8%时间啊,这不得赶紧优化一下

alt
    private String bytesToHexString(byte[] bytes) {
    
    
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

那我后面就把这块代码重构下就行,优化过程大致就是这样啦,大家掌握方法就好

后记

如果你想了解使用Xrebel优化接口性能,可以看看这篇文章:http://blog.zysicyj.top/db82e5f2 我前两天写了优化解析接口性能的,可以看看这篇文章:http://blog.zysicyj.top/a384b09f

本文由 mdnice 多平台发布

Guess you like

Origin blog.csdn.net/njpkhuan/article/details/132726583