【发布时间】:2013-12-27 05:55:55
【问题描述】:
我写了一个测试,试图测试两件事:
- 缓冲区数组的大小是否会影响其性能,即使您不使用整个缓冲区也是如此
- 数组和
ArrayList的相对性能
我对结果有点惊讶
- 盒装数组(即
Integervsint)并不比原始版本慢很多 - 底层数组的大小并不重要
-
ArrayLists 的速度是对应数组的两倍多。
问题
- 为什么
ArrayList这么慢? - 我的基准测试写得好吗?换句话说,我的结果准确吗?
结果
0% Scenario{vm=java, trial=0, benchmark=SmallArray} 34.57 ns; ?=0.79 ns @ 10 trials
17% Scenario{vm=java, trial=0, benchmark=SmallBoxed} 40.40 ns; ?=0.21 ns @ 3 trials
33% Scenario{vm=java, trial=0, benchmark=SmallList} 105.78 ns; ?=0.09 ns @ 3 trials
50% Scenario{vm=java, trial=0, benchmark=BigArray} 34.53 ns; ?=0.05 ns @ 3 trials
67% Scenario{vm=java, trial=0, benchmark=BigBoxed} 40.09 ns; ?=0.23 ns @ 3 trials
83% Scenario{vm=java, trial=0, benchmark=BigList} 105.91 ns; ?=0.14 ns @ 3 trials
benchmark ns linear runtime
SmallArray 34.6 =========
SmallBoxed 40.4 ===========
SmallList 105.8 =============================
BigArray 34.5 =========
BigBoxed 40.1 ===========
BigList 105.9 ==============================
vm: java
trial: 0
代码
这段代码是在 Windows 中使用 Java 7 和 Google caliper 0.5-rc1 编写的(因为上次我检查了 1.0 还不能在 Windows 中运行)。
简要概述:在所有 6 次测试中,在循环的每次迭代中,它将数组的前 128 个单元格中的值相加(无论数组有多大),并将其添加到总值中。 Caliper 告诉我测试应该运行多少次,所以我循环添加了 128 次。
这 6 个测试有 int[]、Integer[] 和 ArrayList<Integer> 的大 (131072) 和小 (128) 版本。你大概可以从名字中找出哪个是哪个。
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;
public class SpeedTest {
public static class TestBenchmark extends SimpleBenchmark {
int[] bigArray = new int[131072];
int[] smallArray = new int[128];
Integer[] bigBoxed = new Integer[131072];
Integer[] smallBoxed = new Integer[128];
List<Integer> bigList = new ArrayList<>(131072);
List<Integer> smallList = new ArrayList<>(128);
@Override
protected void setUp() {
Random r = new Random();
for(int i = 0; i < 128; i++) {
smallArray[i] = Math.abs(r.nextInt(100));
bigArray[i] = smallArray[i];
smallBoxed[i] = smallArray[i];
bigBoxed[i] = smallArray[i];
smallList.add(smallArray[i]);
bigList.add(smallArray[i]);
}
}
public long timeBigArray(int reps) {
long result = 0;
for(int i = 0; i < reps; i++) {
for(int j = 0; j < 128; j++) {
result += bigArray[j];
}
}
return result;
}
public long timeSmallArray(int reps) {
long result = 0;
for(int i = 0; i < reps; i++) {
for(int j = 0; j < 128; j++) {
result += smallArray[j];
}
}
return result;
}
public long timeBigBoxed(int reps) {
long result = 0;
for(int i = 0; i < reps; i++) {
for(int j = 0; j < 128; j++) {
result += bigBoxed[j];
}
}
return result;
}
public long timeSmallBoxed(int reps) {
long result = 0;
for(int i = 0; i < reps; i++) {
for(int j = 0; j < 128; j++) {
result += smallBoxed[j];
}
}
return result;
}
public long timeBigList(int reps) {
long result = 0;
for(int i = 0; i < reps; i++) {
for(int j = 0; j < 128; j++) {
result += bigList.get(j);
}
}
return result;
}
public long timeSmallList(int reps) {
long result = 0;
for(int i = 0; i < reps; i++) {
for(int j = 0; j < 128; j++) {
result += smallList.get(j);
}
}
return result;
}
}
public static void main(String[] args) {
Runner.main(TestBenchmark.class, new String[0]);
}
}
【问题讨论】:
-
那个运行时的运行时是什么?
-
@SamIam 我不确定我是否理解这个问题;运行时是它下面的基准代码。
-
是整个
timeBigBoxed或类似方法所花费的时间吗?这是for循环之一的单次迭代所花费的时间吗? -
Random.nextInt(n) 总是返回一个正数。 BTW Math.abs(n) 不总是返回一个正数。
-
@PeterLawrey 实际上 Random.nextInt(n) 返回一个 非负 数,但您的观点是,在结果上调用 Math.abs() 毫无意义。无论如何+1。 :-)
标签: java arrays performance arraylist