This is the ninth day of my participation in the First Challenge 2022

Hello, everyone. I’m Xiao Hei.

Here’s the thing

During the Spring Festival, I did a small function with MyBatis interceptor plug-in to deal with the audit field in the new project.

After using MyBatis interceptor, the fishing time is longer again. 🐟

I was still feeling happy, but my colleagues from the pressure test team came to me and said that the TPS of my application interface suddenly decreased a lot. Is there a BUG? There is a BUG

emmm… Big New Year, unlucky!

Recently, there is no special function, just a plug-in, but also this problem?

So, we started the investigation.

Problem orientation

Tool jvisualVm

Since we had a dedicated pressure environment with JMX configuration enabled, I connected directly to the JVM host in the pressure environment to do a wave of analysis.

Let’s give everyone the amway tool. Use it early.

JvisualVm is a JDK built-in tool, can monitor threads, memory, view method CPU time and objects in memory, has been GC objects, reverse view allocated stack, and so on, and use very simple, and rich functionality, including most of the other JDK built-in command functions.

JvisualVm is in the BIN directory of the JDK. Double-click to open it and use it.

Right-click on the left to add a remote host.

The host name corresponds to the IP address of the remote host you want to connect to, and the port specifies the JMX port enabled by the remote JVM. This is if your remote JVM has JMX enabled.

Then add the JMX connection on the host.

After you open the JMX connection, you should see the following image.

Real-time monitoring of CPU, memory, threads, etc.

Now that the tools are basically introduced, let’s use this artifact to find out what the problem is.

The sampler looks at the hotspot method

The approach I took was to use jvisualVm’s sampler to directly look at the time consuming of the hot spot method during pressure measurement.

In this result, the one at the top is the one that takes the most time over that period of time.

It is obvious that IbatisAuditDataInterceptor. Intercept () this method cost by 34.7%.

Now that we’ve identified the specific method, let’s see why it’s slow.

The code analysis

Aspect reading, here first stick a code.

Here you might as well take a look at what causes the slowness.

The code logic is relatively simple, that is, some loops and judgments, and some assignment actions, and the data of the loop is to be sure that the data volume is not large.

A special point is that the assignment here are using org.apache.com mons. Beanutils. Beanutils. The setProperty () implementation.

The suspect is that it takes a long time to set the property value because reflection is used.

Problem solving

Once we have a preliminary fix on the problem code, we can try it out.

We know it’s slow because of reflection, so what can we do to make it faster to set properties here?

Of course, setter method is the fastest way to set directly, but I consider that the later integration may be in different applications, and different applications may have different audit field names, to configure, so I still need to do through reflection.

Next, amway goodies.

ReflectAsm

ReflectAsm is a high performance reflection toolkit that performs much better than the JDK’s native reflection for Mehtod execution, and Apache’s BeanUtils.

To use ReflectAsm, you need to import dependencies first. The following uses Maven as an example:

<dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>reflectasm</artifactId>
    <version>1.11.0</version>
</dependency>
Copy the code

The Jar package is very simple, with only five classes:

You only need to use ConstructorAccess and MethodAccess if you want to reflect calling methods.

Take a quick test to see how effective ReflectAsm can be.

/ * * *@authorSaid the little black *@ClassName ReflectDemo
 * @Description
 * @date2022/2/9 * * /
public class ReflectDemo {

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        MethodAccess methodAccess = MethodAccess.get(User.class);
        User user = new User();

        long start, end;

        start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            user.setName("Black said.");
        }
        end = System.currentTimeMillis();
        System.out.println("Setter takes time :"+(end-start));

        start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            methodAccess.invoke(user, "setName"."Black said.");
        }
        end = System.currentTimeMillis();
        System.out.println(MethodAccess takes time:+(end-start));

        start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            BeanUtils.setProperty(user, "setName"."Black said.");
        }
        end = System.currentTimeMillis();

        System.out.println("BeanUtils takes time :"+(end-start)); }}@Data
class User {
    private String name;
}
Copy the code

Using MethodAccess and BeanUtils to set the name attribute of the User object 1,000,000 times by calling the set method directly:

Setter takes 21 methodAccess takes 69 BeanUtils takes 21256Copy the code

As a result, set definitely takes the least time, so MethodAccess takes a little bit more time than set, and notice that this is a million runs.

BeanUtils was a hundred times slower at 21256ms.

So using ReflectAsm should make our plug-in execution much less time-consuming, so let’s shake it up.

In addition to tuning the reflection to METHOD_ACCESS, and extracting the duplicate code into the two methods.

After resubmitting the code for pressure testing, the problem is fixed and you’re happy to fish again.

The last

The above is the record of a small problem investigation and transformation by Hei. I hope it can be helpful to you when you encounter similar problems.

This article also mainly gives you two amway tools.

One is jvisualVm, which can be used for memory, GC, thread and other problems.

ReflectAsm is a high-performance reflection tool. You can use it when performing reflection operations in the future.

I am xiao Hei, a programmer in the Internet “casual”, have a public number [Xiao Hei said Java]

Like + favorites + attention, three go a wave ~ ❤