Java 使用StopWatch输出代码执行耗时以及执行时间百分比

一、需求

有时候代码中需要监控某个方法的具体执行时间,从网上找了找资料,简单整理一下

二、pom依赖


        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
            <scope>compile</scope>
        </dependency>

三、两种实现方式:工具类、切面

(一)、注解方式(推荐使用)

1、自定义注解
package com.example.stopwatch.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface StopWatch {
    String value() default "";
}
2、编写切面
package com.example.stopwatch;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;


/**
 * @version 1.0
 * @description: 方法执行时间切面
 * @date 2023/3/29 14:54
 */
@Slf4j
@Aspect
@Component
public class StopWatchAspect {

    @Pointcut("@annotation(com.example.stopwatch.annotation.StopWatch)")
    public void stopWatchPointCut() {
    }

    @Around("stopWatchPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {

        return logCostTime(point);
    }

    private Object logCostTime(ProceedingJoinPoint joinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        stopWatch.start("class:" + className + " method:" + methodName);
        //执行方法
        Object result = joinPoint.proceed();
        stopWatch.stop();
        log.info("log-" + stopWatch.toString());
        return result;
    }
}

(二)、工具类方式

1、工具类代码
package com.example.stopwatch;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author:
 * @Description
 * @Date: 下午6:29 2023/4/20
 */
public class StopWatchUtil {

    private final String id;
    private List<StopWatchUtil.TaskInfo> taskList;
    private String currentTaskName;
    private long startTimeNanos;
    private StopWatchUtil.TaskInfo lastTaskInfo;
    private int taskCount;
    private long totalTimeNanos;

    public StopWatchUtil() {
        this("");
    }

    public StopWatchUtil(String id) {
        this(id, true);
    }

    public StopWatchUtil(String id, boolean keepTaskList) {
        this.id = id;
        if (keepTaskList) {
            this.taskList = new ArrayList();
        }

    }

    public String getId() {
        return this.id;
    }

    public void setKeepTaskList(boolean keepTaskList) {
        if (keepTaskList) {
            if (null == this.taskList) {
                this.taskList = new ArrayList();
            }
        } else {
            this.taskList = null;
        }

    }

    public void start() throws IllegalStateException {
        this.start("");
    }

    public void start(String taskName) throws IllegalStateException {
        if (null != this.currentTaskName) {
            throw new IllegalStateException("Can't start StopWatch: it's already running");
        } else {
            this.currentTaskName = taskName;
            this.startTimeNanos = System.nanoTime();
        }
    }

    public void stop() throws IllegalStateException {
        if (null == this.currentTaskName) {
            throw new IllegalStateException("Can't stop StopWatch: it's not running");
        } else {
            long lastTime = System.nanoTime() - this.startTimeNanos;
            this.totalTimeNanos += lastTime;
            this.lastTaskInfo = new StopWatchUtil.TaskInfo(this.currentTaskName, lastTime);
            if (null != this.taskList) {
                this.taskList.add(this.lastTaskInfo);
            }

            ++this.taskCount;
            this.currentTaskName = null;
        }
    }

    public boolean isRunning() {
        return this.currentTaskName != null;
    }

    public String currentTaskName() {
        return this.currentTaskName;
    }

    public long getLastTaskTimeNanos() throws IllegalStateException {
        if (this.lastTaskInfo == null) {
            throw new IllegalStateException("No tasks run: can't get last task interval");
        } else {
            return this.lastTaskInfo.getTimeNanos();
        }
    }

    public long getLastTaskTimeMillis() throws IllegalStateException {
        if (this.lastTaskInfo == null) {
            throw new IllegalStateException("No tasks run: can't get last task interval");
        } else {
            return this.lastTaskInfo.getTimeMillis();
        }
    }

    public String getLastTaskName() throws IllegalStateException {
        if (this.lastTaskInfo == null) {
            throw new IllegalStateException("No tasks run: can't get last task name");
        } else {
            return this.lastTaskInfo.getTaskName();
        }
    }

    public StopWatchUtil.TaskInfo getLastTaskInfo() throws IllegalStateException {
        if (this.lastTaskInfo == null) {
            throw new IllegalStateException("No tasks run: can't get last task info");
        } else {
            return this.lastTaskInfo;
        }
    }

    public long getTotalTimeNanos() {
        return this.totalTimeNanos;
    }

    public long getTotalTimeMillis() {
        return nanosToMillis(this.totalTimeNanos);
    }

    public double getTotalTimeSeconds() {
        return nanosToSeconds(this.totalTimeNanos);
    }

    public int getTaskCount() {
        return this.taskCount;
    }

    public StopWatchUtil.TaskInfo[] getTaskInfo() {
        if (null == this.taskList) {
            throw new UnsupportedOperationException("Task info is not being kept!");
        } else {
            return (StopWatchUtil.TaskInfo[]) this.taskList.toArray(new StopWatchUtil.TaskInfo[0]);
        }
    }

    public String shortSummary() {
        return stringFormat("StopWatch '{}': running time = {} ns", this.id, new Object[]{this.totalTimeNanos});
    }

    public String prettyPrint() {
        String lineSeparator = System.lineSeparator();
        StringBuilder sb = new StringBuilder(this.shortSummary());
        sb.append(lineSeparator);
        if (null == this.taskList) {
            sb.append("No task info kept");
        } else {
            sb.append("---------------------------------------------").append(lineSeparator);
            sb.append("ns         %     Task name").append(lineSeparator);
            sb.append("---------------------------------------------").append(lineSeparator);
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setMinimumIntegerDigits(9);
            nf.setGroupingUsed(false);
            NumberFormat pf = NumberFormat.getPercentInstance();
            pf.setMinimumIntegerDigits(3);
            pf.setGroupingUsed(false);
            StopWatchUtil.TaskInfo[] var5 = this.getTaskInfo();
            int var6 = var5.length;

            for (int var7 = 0; var7 < var6; ++var7) {
                StopWatchUtil.TaskInfo task = var5[var7];
                sb.append(nf.format(task.getTimeNanos())).append("  ");
                sb.append(pf.format((double) task.getTimeNanos() / (double) this.getTotalTimeNanos())).append("  ");
                sb.append(task.getTaskName()).append(lineSeparator);
            }
        }

        return sb.toString();
    }

    public String toString() {
        StringBuilder sb = new StringBuilder(this.shortSummary());
        if (null == this.taskList) {
            StopWatchUtil.TaskInfo[] var2 = this.getTaskInfo();
            int var3 = var2.length;

            for (int var4 = 0; var4 < var3; ++var4) {
                StopWatchUtil.TaskInfo task = var2[var4];
                sb.append("; [").append(task.getTaskName()).append("] took ").append(task.getTimeNanos()).append(" ns");
                long percent = Math.round(100.0D * (double) task.getTimeNanos() / (double) this.getTotalTimeNanos());
                sb.append(" = ").append(percent).append("%");
            }
        } else {
            sb.append("; no task info kept");
        }

        return sb.toString();
    }


    public static long nanosToMillis(long duration) {
        return TimeUnit.NANOSECONDS.toMillis(duration);
    }

    public static double nanosToSeconds(long duration) {
        return (double) duration / 1.0E9D;
    }


    public static String stringFormat(String message, String delimStr, Object... argArray) {
        if (message == null) {
            return message;
        } else if (argArray == null) {
            return message;
        } else {
            if (delimStr == null || delimStr.length() == 0) {
                delimStr = "{}";
            }

            int i = 0;
            StringBuilder sbuf = new StringBuilder(message.length() + 50);

            for (int L = 0; L < argArray.length; ++L) {
                int j = message.indexOf(delimStr, i);
                if (j == -1) {
                    if (i == 0) {
                        return message;
                    }

                    sbuf.append(message, i, message.length());
                    return sbuf.toString();
                }

                sbuf.append(message, i, j);
                deeplyAppendParameter(sbuf, argArray[L], new HashMap());
                i = j + delimStr.length();
            }

            sbuf.append(message, i, message.length());
            return sbuf.toString();
        }
    }

    private static void deeplyAppendParameter(StringBuilder sbuf, Object o, Map<Object[], Object> seenMap) {
        if (o == null) {
            sbuf.append("null");
        } else {
            if (!o.getClass().isArray()) {
                safeObjectAppend(sbuf, o);
            } else if (o instanceof boolean[]) {
                booleanArrayAppend(sbuf, (boolean[]) ((boolean[]) o));
            } else if (o instanceof byte[]) {
                byteArrayAppend(sbuf, (byte[]) ((byte[]) o));
            } else if (o instanceof char[]) {
                charArrayAppend(sbuf, (char[]) ((char[]) o));
            } else if (o instanceof short[]) {
                shortArrayAppend(sbuf, (short[]) ((short[]) o));
            } else if (o instanceof int[]) {
                intArrayAppend(sbuf, (int[]) ((int[]) o));
            } else if (o instanceof long[]) {
                longArrayAppend(sbuf, (long[]) ((long[]) o));
            } else if (o instanceof float[]) {
                floatArrayAppend(sbuf, (float[]) ((float[]) o));
            } else if (o instanceof double[]) {
                doubleArrayAppend(sbuf, (double[]) ((double[]) o));
            } else {
                objectArrayAppend(sbuf, (Object[]) ((Object[]) o), seenMap);
            }

        }
    }

    private static void objectArrayAppend(StringBuilder sbuf, Object[] a, Map<Object[], Object> seenMap) {
        sbuf.append('[');
        if (!seenMap.containsKey(a)) {
            seenMap.put(a, (Object) null);
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                deeplyAppendParameter(sbuf, a[i], seenMap);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            seenMap.remove(a);
        } else {
            sbuf.append("...");
        }

        sbuf.append(']');
    }

    private static void booleanArrayAppend(StringBuilder sbuf, boolean[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void byteArrayAppend(StringBuilder sbuf, byte[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void charArrayAppend(StringBuilder sbuf, char[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void shortArrayAppend(StringBuilder sbuf, short[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void intArrayAppend(StringBuilder sbuf, int[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void longArrayAppend(StringBuilder sbuf, long[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void floatArrayAppend(StringBuilder sbuf, float[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void doubleArrayAppend(StringBuilder sbuf, double[] a) {
        sbuf.append('[');
        int len = a.length;

        for (int i = 0; i < len; ++i) {
            sbuf.append(a[i]);
            if (i != len - 1) {
                sbuf.append(", ");
            }
        }

        sbuf.append(']');
    }

    private static void safeObjectAppend(StringBuilder sbuf, Object o) {
        try {
            String oAsString = o.toString();
            sbuf.append(oAsString);
        } catch (Throwable var3) {
            sbuf.append("[FAILED toString()]");
        }

    }


    public static final class TaskInfo {
        private final String taskName;
        private final long timeNanos;

        TaskInfo(String taskName, long timeNanos) {
            this.taskName = taskName;
            this.timeNanos = timeNanos;
        }

        public String getTaskName() {
            return this.taskName;
        }

        public long getTimeNanos() {
            return this.timeNanos;
        }

        public long getTimeMillis() {
            return nanosToMillis(this.timeNanos);
        }

        public double getTimeSeconds() {
            return nanosToSeconds(this.timeNanos);
        }
    }

}

四、测试类

package com.example.stopwatch;

import com.alibaba.fastjson.JSON;
import com.example.stopwatch.annotation.StopWatch;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @Author:
 * @Description
 * @Date: 下午5:06 2023/4/20
 */
@Slf4j
@Service
public class StopWatchTest {

    /**
     * 注解方式
     */
    @StopWatch
    public void test() {
        log.info("StopWatch注解开始测试");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 直接写到方法中
     */
    public static void test1() {
        log.info("StopWatch工具类开始测试");
        try {
            StopWatchUtil stopWatch = new StopWatchUtil();
            stopWatch.start("测试一开始");
            Thread.sleep(1000);
            stopWatch.stop();
            stopWatch.start("测试二开始");
            Thread.sleep(3000);
            stopWatch.stop();
            log.info("*********所有任务总耗时:{}毫秒", stopWatch.getTotalTimeMillis());
            log.info("*********耗时详情:{}", JSON.toJSONString(stopWatch.getTaskInfo()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        test1();
    }

}

五、接口类测试注解方式使用

package com.example.api;

import com.example.service.ExcelService;
import com.example.stopwatch.StopWatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

/**
 * @Author:
 * @Description
 * @Date: 下午2:00 2023/4/18
 */
@RestController
@RequestMapping("/excel")
public class ExcelApi {

    @Autowired
    private ExcelService excelService;
    @Autowired
    private StopWatchTest stopWatchTest;

    @GetMapping("test1")
    public String test1() {
        stopWatchTest.test();
        return "成功";
    }

    /**
     * 直接输出到前端
     *
     * @param response
     */
    @GetMapping("/export/one")
    public void downloadOne(HttpServletResponse response) {
        excelService.exportExcelByDtoClientNew(response);
    }

    /**
     * 先将文件写到本地,然后读取文件,返回给前端,最后删除本地文件
     *
     * @param response
     */
    @GetMapping("/export")
    public void download(HttpServletResponse response) {
        excelService.exportExcelByDtoClient(response);
    }

}

六、结果

1、工具类测试结果(直接执行四种的main方法):

在这里插入图片描述

2、注解测试结果(启动项目):浏览器访问:http://localhost:8080/excel/test1

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值