You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效统计Java大型方法内多段代码的执行耗时?

优化大型方法内多段代码计时的方案

针对你遇到的手动维护时间戳变量易出错、Guava Stopwatch调用繁琐、上线清理计时代码风险高的问题,提供以下几个实用优化方案:

1. 封装阶段式计时工具类

基于Guava Stopwatch封装一个支持多阶段记录的工具类,消除重复的stop()/reset()调用,自动管理阶段耗时记录:

import com.google.common.base.Stopwatch;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class StageStopwatch {
    private final Stopwatch stopwatch;
    private final List<Stage> stages = new ArrayList<>();
    private String currentStage;

    public static StageStopwatch createStarted() {
        return new StageStopwatch(Stopwatch.createStarted());
    }

    private StageStopwatch(Stopwatch stopwatch) {
        this.stopwatch = stopwatch;
    }

    // 切换到新的计时阶段,自动记录上一阶段耗时
    public void startStage(String stageName) {
        if (currentStage != null) {
            stopwatch.stop();
            stages.add(new Stage(currentStage, stopwatch.elapsed(TimeUnit.NANOSECONDS)));
        }
        currentStage = stageName;
        stopwatch.reset();
        stopwatch.start();
    }

    // 结束所有计时并返回结果
    public List<Stage> finish() {
        if (currentStage != null) {
            stopwatch.stop();
            stages.add(new Stage(currentStage, stopwatch.elapsed(TimeUnit.NANOSECONDS)));
            currentStage = null;
        }
        return new ArrayList<>(stages);
    }

    // 一键打印所有阶段耗时
    public void printAllStages() {
        finish().forEach(stage -> 
            System.out.printf("阶段「%s」耗时: %d ns%n", stage.name, stage.durationNanos)
        );
    }

    public static class Stage {
        public final String name;
        public final long durationNanos;

        Stage(String name, long durationNanos) {
            this.name = name;
            this.durationNanos = durationNanos;
        }
    }
}

使用示例

public static void largeMethod() {
    StageStopwatch timer = StageStopwatch.createStarted();

    timer.startStage("初始化模块");
    System.out.println("it takes a long time ~N sec");

    timer.startStage("核心逻辑1");
    System.out.println("it takes a long time ~N sec");

    timer.startStage("核心逻辑2");
    System.out.println("it takes a long time ~N sec");

    // 输出所有阶段耗时
    timer.printAllStages();
}

这个工具类自动处理阶段切换的计时逻辑,不用手动维护多个时间变量或重复调用Stopwatch的控制方法,代码可读性更高。

2. 用开关控制计时代码,避免上线手动清理

通过静态常量开关控制计时逻辑是否生效,上线时只需修改开关值,无需手动删除代码,减少出错风险:

// 全局计时开关,上线时设为false
public class TimingSwitch {
    public static final boolean ENABLE_TIMING = true;
}

结合Lambda封装计时逻辑,让业务代码与计时代码解耦:

import com.google.common.base.Stopwatch;
import java.util.function.Supplier;

public class TimingHelper {
    // 无返回值的代码块计时
    public static void timed(String stageName, Runnable task) {
        if (!TimingSwitch.ENABLE_TIMING) {
            task.run();
            return;
        }
        Stopwatch sw = Stopwatch.createStarted();
        try {
            task.run();
        } finally {
            sw.stop();
            System.out.printf("阶段「%s」耗时: %s%n", stageName, sw.elapsed());
        }
    }

    // 有返回值的代码块计时
    public static <T> T timed(String stageName, Supplier<T> task) {
        if (!TimingSwitch.ENABLE_TIMING) {
            return task.get();
        }
        Stopwatch sw = Stopwatch.createStarted();
        try {
            return task.get();
        } finally {
            sw.stop();
            System.out.printf("阶段「%s」耗时: %s%n", stageName, sw.elapsed());
        }
    }
}

使用示例

public static void largeMethod() {
    TimingHelper.timed("初始化模块", () -> {
        System.out.println("it takes a long time ~N sec");
    });

    TimingHelper.timed("核心逻辑1", () -> {
        System.out.println("it takes a long time ~N sec");
    });

    TimingHelper.timed("核心逻辑2", () -> {
        System.out.println("it takes a long time ~N sec");
    });
}

当ENABLE_TIMING设为false时,JVM会自动优化掉所有计时相关的冗余代码,不会影响线上性能。

3. 离线性能测试:用JMH替代临时计时

如果你的需求是严谨的性能调优而非线上临时调试,推荐使用JMH(Java Microbenchmark Harness)。它专门针对Java代码的基准测试设计,能避免JIT编译、缓存等因素带来的误差,提供精准的性能数据。

JMH示例片段

import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(1)
@Warmup(iterations = 3)
@Measurement(iterations = 5)
public class LargeMethodBenchmark {

    @Benchmark
    public void testInitialization() {
        System.out.println("it takes a long time ~N sec");
    }

    @Benchmark
    public void testCoreLogic1() {
        System.out.println("it takes a long time ~N sec");
    }
}

JMH适合在离线环境做性能对比测试,不适合嵌入到线上业务代码中。


内容的提问来源于stack exchange,提问作者Hi computer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:07:44