我正在玩 JMH ( http://openjdk.java.net/projects/code-tools/jmh/ ),我只是偶然发现了一个奇怪的结果。
#clone()
我正在对制作数组的浅拷贝的方法进行基准测试,我可以观察到预期的结果(循环遍历数组是一个坏主意,System#arraycopy()
并且在性能方面没有显着差异Arrays#copyOf()
)。
除了System#arraycopy()
当数组的长度被硬编码时会慢四分之一......等等,什么?这怎么能慢?
有谁知道可能是什么原因?
结果(吞吐量):
# JMH 1.11 (released 17 days ago)
# VM version: JDK 1.8.0_05, VM 25.5-b02
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home/jre/bin/java
# VM options: -Dfile.encoding=UTF-8 -Duser.country=FR -Duser.language=fr -Duser.variant
# Warmup: 20 iterations, 1 s each
# Measurement: 20 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
Benchmark Mode Cnt Score Error Units
ArrayCopyBenchmark.ArraysCopyOf thrpt 20 67100500,319 ± 455252,537 ops/s
ArrayCopyBenchmark.ArraysCopyOf_Class thrpt 20 65246374,290 ± 976481,330 ops/s
ArrayCopyBenchmark.ArraysCopyOf_Class_ConstantSize thrpt 20 65068143,162 ± 1597390,531 ops/s
ArrayCopyBenchmark.ArraysCopyOf_ConstantSize thrpt 20 64463603,462 ± 953946,811 ops/s
ArrayCopyBenchmark.Clone thrpt 20 64837239,393 ± 834353,404 ops/s
ArrayCopyBenchmark.Loop thrpt 20 21070422,097 ± 112595,764 ops/s
ArrayCopyBenchmark.Loop_ConstantSize thrpt 20 24458867,274 ± 181486,291 ops/s
ArrayCopyBenchmark.SystemArrayCopy thrpt 20 66688368,490 ± 582416,954 ops/s
ArrayCopyBenchmark.SystemArrayCopy_ConstantSize thrpt 20 48992312,357 ± 298807,039 ops/s
和基准类:
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
@State(Scope.Benchmark)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public class ArrayCopyBenchmark {
private static final int LENGTH = 32;
private Object[] array;
@Setup
public void before() {
array = new Object[LENGTH];
for (int i = 0; i < LENGTH; i++) {
array[i] = new Object();
}
}
@Benchmark
public Object[] Clone() {
Object[] src = this.array;
return src.clone();
}
@Benchmark
public Object[] ArraysCopyOf() {
Object[] src = this.array;
return Arrays.copyOf(src, src.length);
}
@Benchmark
public Object[] ArraysCopyOf_ConstantSize() {
Object[] src = this.array;
return Arrays.copyOf(src, LENGTH);
}
@Benchmark
public Object[] ArraysCopyOf_Class() {
Object[] src = this.array;
return Arrays.copyOf(src, src.length, Object[].class);
}
@Benchmark
public Object[] ArraysCopyOf_Class_ConstantSize() {
Object[] src = this.array;
return Arrays.copyOf(src, LENGTH, Object[].class);
}
@Benchmark
public Object[] SystemArrayCopy() {
Object[] src = this.array;
int length = src.length;
Object[] array = new Object[length];
System.arraycopy(src, 0, array, 0, length);
return array;
}
@Benchmark
public Object[] SystemArrayCopy_ConstantSize() {
Object[] src = this.array;
Object[] array = new Object[LENGTH];
System.arraycopy(src, 0, array, 0, LENGTH);
return array;
}
@Benchmark
public Object[] Loop() {
Object[] src = this.array;
int length = src.length;
Object[] array = new Object[length];
for (int i = 0; i < length; i++) {
array[i] = src[i];
}
return array;
}
@Benchmark
public Object[] Loop_ConstantSize() {
Object[] src = this.array;
Object[] array = new Object[LENGTH];
for (int i = 0; i < LENGTH; i++) {
array[i] = src[i];
}
return array;
}
}