当我在大循环中使用 Arraylist.add() 方法时,Java 8 比 Java 17 更快。
这就是为什么?这是因为方法
calculateCapacity(Object[] elementData, int minCapacity)
吗?
这是我的代码:
public class T2 {
static Map<String, Object> map = new HashMap<>();
static {
map.put("key", "value");
}
// loop for 10000000 times
public static long TIMES = 10000000;
/**
* run with jdk17 and jdk8
* @param args
*/
public static void main(String[] args) {
long l1 = 0;
int ii = 10;
for (int i = 0; i < ii; i++) {
StopWatch s = new StopWatch();
s.start();
t3();
s.stop();
l1 += s.getTotalTimeMillis();
System.out.println(s.getTotalTimeMillis());
System.out.println(s.prettyPrint());
}
System.out.println("loop" + ii + "times");
System.out.println("Average time :" + l1 / ii+"ms");
}
static void t3() {
Object o = map.get("key");
List<String> s = new ArrayList<>();
for (int i = 0; i < TIMES; i++) {
s.add(o.toString());
}
}
}
我已在 Windows 11 和 macOS 上运行此程序,获得了相同的结果:Java 8 比 Java 17 更快。
性能可能会因 JVM 优化、垃圾收集和底层数据结构等各种因素而有所不同。然而,在 Java 8 和 Java 17 中,
ArrayList.add()
方法基本上是相似的。
一个具体的区别是您提到的
calculateCapacity
方法。在 Java 17 中,ArrayList
使用 ArraysSupport.newLength
进行更强大的溢出检查,这可能会增加一些开销。然而,对于大多数用例来说,这种开销通常可以忽略不计。
如果您始终观察到显着差异,请确保:
总而言之,虽然实现上可能存在细微差别,但对于大多数应用程序来说,它们不应导致显着的性能差异。正确的基准测试是准确绩效评估的关键。
您当前的基准测试方法有一些局限性:
更好的方法是使用 Java Microbenchmarking Harness (JMH)。它是一个专为性能基准测试而设计的 Java 库,它控制许多可能影响性能测量的变量。
以下是使用 JMH 时您的代码的外观:
import org.openjdk.jmh.annotations.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class MyBenchmark {
static Map<String, Object> map = new HashMap<>();
static {
map.put("key", "value");
}
static final long TIMES = 10000000;
Object o = map.get("key");
@Benchmark
public void testArrayListAdd() {
List<String> s = new ArrayList<>();
for (int i = 0; i < TIMES; i++) {
s.add(o.toString());
}
}
}
要运行此程序,您需要将 JMH 作为依赖项包含在内,然后执行基准测试。
这可以让您更准确地衡量不同版本的 Java 之间的性能差异。