介绍
衡量代码执行时间是编写高效应用程序的关键步骤。在一台可能为大量用户服务的机器上,对代码的时间感知可以让您进一步规划,并考虑执行时间。
在多线程系统中,测量单个线程或异步任务的执行时间也很有用。
由于在基于Java-for-Spring的解决方案中没有内置的、方便的方法来度量代码执行,所以我们介绍了StopWatch工具。
在本教程中,我们将了解如何使用Spring的秒表测量Java中的代码执行时间。
StopWatch是一个实用程序类,在util包中重新排序。它有一个非常简单的API,允许我们对指定的任务、任务组和程序的总运行时间计时。
此类通常用于在开发阶段检查代码的性能,而不是生产应用程序的一部分。
注意:值得注意的是秒表不是线程安全的。
它依赖于System.nanoTime(),以南秒为单位跟踪时间,这是人们一直在手动执行代码的时间。
StopWatch属于Spring的核心util包:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
当然,它也存在于spring boot starter web依赖中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
StopWatch的API可以归结为创建一个实例并调用start()和stop()——就像用实际的StopWatch计时代码一样。开始计时时,还可以提供一个字符串,用作关联任务的名称或注释。这有助于在结果中区分它们。
任务只是start()和stop()调用之间的时间段。对于在StopWatch启动时创建的每个任务,其名称和执行时间保存在TaskInfo实例中,并添加到任务列表中。
让我们继续创建一个任务,使用名称并度量一段代码的执行时间:
StopWatch timeMeasure = new StopWatch();
timeMeasure.start("Task 1");
Thread.sleep(1000);
timeMeasure.stop();
System.out.println("Last task time in Millis: "
+ timeMeasure.getLastTaskMillis());
运行结果
Last task time in Millis: 1009
您可以通过getTotalTimeSeconds()、getTotalTimeMillis()和getTotalTimeNanos()访问所有任务的总和。
您还可以通过getLastTaskInfo()访问秒表的最后一个任务,它返回一个TaskInfo实例。此实例包含有关上一个任务的信息,例如名称以及它花费的时间(以秒、毫秒和纳秒为单位):
运行结果
Task 1
1008
在处理多个任务时,一个非常方便的方法是prettyPrint()方法,它以类似表格的方式打印所有记录,格式简单:
// Naming this StopWatch instance
StopWatch stopWatch = new StopWatch("Measure Code Execution");
stopWatch.start("1. Task");
Thread.sleep(2000);
stopWatch.stop();
stopWatch.start("2. Task");
Thread.sleep(5000);
stopWatch.stop();
stopWatch.start("3. Task");
Thread.sleep(3000);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
输出
StopWatch 'Measure Code Execution': running time = 10012348500 ns
---------------------------------------------
ns % Task name
---------------------------------------------
2002729600 020% 1. Task
5006985700 050% 2. Task
3002633200 030% 3. Task
注意:如果我们使用StopWatch来测量大量时间间隔(几十万或数百万的顺序)的代码执行时间,TaskInfo列表将消耗大量的工作内存。您可以通过以下方式关闭:
stopWatch.setKeepTaskList(false);