How to elegantly count block time in Java

In our actual development, more or less will encounter statistics of a piece of code time-consuming situation, we generally write as follows

long start = System.currentTimeMillis();
try {
    / /... Specific code snippets
} finally {
    System.out.println("cost: " + (System.currentTimeMillis() - start));
}
Copy the code

There’s nothing wrong with it, but it doesn’t look pretty, so what’s a more elegant way to write it?

1. Agency

Those of you who know Spring AOP may immediately think of a workaround. If you want to count the time spent on a method, use a tangential non-intrusive implementation such as

// Define a pointcut to intercept all methods that meet the criteria
@Pointcut("execution(public * com.git.hui.boot.aop.demo.*.*(*))")
public void point(a) {}@Around("point()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    try{
        return joinPoint.proceed();
    } finally {
        System.out.println("cost: "+ (System.currentTimeMillis() - start)); }}Copy the code

Spring AOP’s underlying support principle is the proxy pattern, which provides enhanced functionality for target objects. In the Spring ecosystem, using AOP to measure method time is less intrusive and easy to implement, but there are several problems

  • The statistical granularity is method level
  • Class internal method calls do not take effect.

2. AutoCloseable

A new interface, AutoCloseable, was introduced in JDK1.7. Its implementation class is usually used in conjunction with try{}, which is often seen in IO streams

// Read the contents of the file and output it
try (Reader stream = new BufferedReader(new InputStreamReader(new FileInputStream("/tmp")))) {
    List<String> list = ((BufferedReader) stream).lines().collect(Collectors.toList());
    System.out.println(list);
} catch (IOException e) {
    e.printStackTrace();
}
Copy the code

The main reason for this is that the AutoCloseable#close method is called after the try(){} is executed.

The next Cost class implements the AutoCloseable interface, which records a time when it is created, a time in the close method, and outputs the time difference. Put the logic that takes time to count into the try(){} code block

Here is a concrete implementation:

public static class Cost implements AutoCloseable {
    private long start;

    public Cost(a) {
        this.start = System.currentTimeMillis();
    }

    @Override
    public void close(a) {
        System.out.println("cost: "+ (System.currentTimeMillis() - start)); }}public static void testPrint(a) {
    for (int i = 0; i < 5; i++) {
        System.out.println("now " + i);
        try {
            Thread.sleep(10);
        } catch(InterruptedException e) { e.printStackTrace(); }}}public static void main(String[] args) {
    try (Cost c = new Cost()) {
        testPrint();
    }
    System.out.println("------over-------");
}
Copy the code

The following output is displayed:

now 0
now 1
now 2
now 3
now 4
cost: 55
------over-------
Copy the code

If the code block throws an exception, will the time output be normal?

public static void testPrint(a) {
    for (int i = 0; i < 5; i++) {
        System.out.println("now " + i);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (i == 3) {
            throw new RuntimeException("some exception!"); }}}Copy the code

Output the following again, no problem

now 0
now 1
now 2
now 3
cost: 46
Exception in thread "main" java.lang.RuntimeException: some exception!
	at com.git.hui.boot.order.Application.testPrint(Application.java:43)
	at com.git.hui.boot.order.Application.main(Application.java:50)
Copy the code

3. Summary

In addition to the two approaches described above, there is another approach that is less common in business development, but can be seen in middleware, functional components of basic services, using JavaAgent probe technology. For example, Ali’s Arthas uses JavaAgent to do a variety of functions. This will be covered later in the introduction to Java Probe technology

Here are three ways to count time

Basic writing

long start = System.currentTimeMillis();
try {
    / /... Specific code snippets
} finally {
    System.out.println("cost: " + (System.currentTimeMillis() - start));
}
Copy the code

Advantages are simple, wide range of application; The disadvantage is that it is highly intrusive and has a lot of duplicate code

Spring AOP

In the Spring ecosystem, AOP can be used to intercept target methods and count the elapsed time

@Around("...")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    try{
        return joinPoint.proceed();
    } finally {
        System.out.println("cost: "+ (System.currentTimeMillis() - start)); }}Copy the code

Advantages: Non-intrusive, suitable for unified management (for example, the test environment output statistics time, production environment does not output); The disadvantages are that the scope is small, the granularity is method level, and the scope of use of AOP is limited

AutoCloseable

So this is kind of an advanced version of the first one

/ / define the class
public static class Cost implements AutoCloseable {
    private long start;

    public Cost(a) {
        this.start = System.currentTimeMillis();
    }

    @Override
    public void close(a) {
        System.out.println("cost: "+ (System.currentTimeMillis() - start)); }}// Use gestures
try (Cost c = new Cost()) {
    ...
}
Copy the code

Advantages are: simple, wide range of application, and suitable for unified management; The downside is that there is still code intrusion

instructions

The second method above seems to be the most elegant, but restrictive; If there is a need for more flexibility, it is recommended to consider the third method, which is much more elegant in terms of code simplicity and unified management, and can reduce a lot of redundant code compared with the first method

II. The other

1. A gray Blog:liuyueyi.github.io/hexblog

A gray personal blog, recording all the study and work in the blog, welcome everyone to go to stroll

2. Statement

As far as the letter is not as good as, has been the content, purely one’s own words, because of the limited personal ability, it is hard to avoid omissions and mistakes, such as finding bugs or better suggestions, welcome criticism and correction, not grudging gratitude

  • Micro Blog address: Small Gray Blog
  • QQ: a gray /3302797840

3. Scan attention

A gray blog