Java - Vector vs ArrayList 性能 - 测试 [英] Java - Vector vs ArrayList performance - test
问题描述
因为性能的原因,每个人都说应该使用vector(因为Vector 在每次操作之后都会同步).我写了一个简单的测试:
Everybody's saying that one should use vector because of the perfomance (cause Vector synchronizes after every operation and stuff). I've written a simple test:
import java.util.ArrayList;
import java.util.Date;
import java.util.Vector;
public class ComparePerformance {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
Vector<Integer> vector = new Vector<Integer>();
int size = 10000000;
int listSum = 0;
int vectorSum = 0;
long startList = new Date().getTime();
for (int i = 0; i < size; i++) {
list.add(new Integer(1));
}
for (Integer integer : list) {
listSum += integer;
}
long endList = new Date().getTime();
System.out.println("List time: " + (endList - startList));
long startVector = new Date().getTime();
for (int i = 0; i < size; i++) {
vector.add(new Integer(1));
}
for (Integer integer : list) {
vectorSum += integer;
}
long endVector = new Date().getTime();
System.out.println("Vector time: " + (endVector - startVector));
}
}
结果如下:
List time: 4360
Vector time: 4103
基于此,Vector
在迭代和阅读方面的性能似乎稍好一些.也许这是一个愚蠢的问题,或者我做了错误的假设 - 有人可以解释一下吗?
Based on this it seems that Vector
perfomance at iterating over and reading is slightly better. Maybe this is a dumb queston or I've made wrong assumptions - can somebody please explan this?
推荐答案
您编写了一个简单的微基准测试.在 JVM 上进行微基准测试是一项非常棘手的工作,要列举所有陷阱甚至并不容易,但这里有一些经典的:
You have written a naïve microbenchmark. Microbenchmarking on the JVM is very tricky business and it is not even easy to enumerate all the pitfalls, but here are some classic ones:
- 你必须预热代码;
- 您必须控制垃圾收集暂停;
System.currentTimeMillis
不精确,但您似乎甚至不知道这种方法(您的new Date().getTime()
是等效的,但是较慢).
- you must warm up the code;
- you must control for garbage collection pauses;
System.currentTimeMillis
is imprecise, but you don't seem to be aware of even this method (yournew Date().getTime()
is equivalent, but slower).
如果您想正确执行此操作,请查看 Oracle 的 jmh
工具或 Google 的 Caliper.
If you want to do this properly, then check out Oracle's jmh
tool or Google's Caliper.
由于我对自己看到这些数字很感兴趣,这里是 jmh
的输出.一、测试代码:
Since I was kind of interested to see these numbers myself, here is the output of jmh
. First, the test code:
public class Benchmark1
{
static Integer[] ints = new Integer[0];
static {
final List<Integer> list = new ArrayList(asList(1,2,3,4,5,6,7,8,9,10));
for (int i = 0; i < 5; i++) list.addAll(list);
ints = list.toArray(ints);
}
static List<Integer> intList = Arrays.asList(ints);
static Vector<Integer> vec = new Vector<Integer>(intList);
static List<Integer> list = new ArrayList<Integer>(intList);
@GenerateMicroBenchmark
public Vector<Integer> testVectorAdd() {
final Vector<Integer> v = new Vector<Integer>();
for (Integer i : ints) v.add(i);
return v;
}
@GenerateMicroBenchmark
public long testVectorTraverse() {
long sum = (long)Math.random()*10;
for (int i = 0; i < vec.size(); i++) sum += vec.get(i);
return sum;
}
@GenerateMicroBenchmark
public List<Integer> testArrayListAdd() {
final List<Integer> l = new ArrayList<Integer>();
for (Integer i : ints) l.add(i);
return l;
}
@GenerateMicroBenchmark
public long testArrayListTraverse() {
long sum = (long)Math.random()*10;
for (int i = 0; i < list.size(); i++) sum += list.get(i);
return sum;
}
}
结果:
testArrayListAdd 234.896 ops/msec
testVectorAdd 274.886 ops/msec
testArrayListTraverse 1718.711 ops/msec
testVectorTraverse 34.843 ops/msec
注意以下几点:
- 在
...add
方法中,我正在创建一个新的本地集合.JIT 编译器使用这一事实并省略对Vector
方法的锁定——因此性能几乎相同; - 在
...traverse
方法中,我正在从全局集合中读取数据;锁不能被忽略,而这正是Vector
真正的性能损失出现的地方.
- in the
...add
methods I am creating a new, local collection. The JIT compiler uses this fact and elides the locking onVector
methods—hence almost equal performance; - in the
...traverse
methods I am reading from a global collection; the locks cannot be elided and this is where the true performance penalty ofVector
shows up.
主要结论应该是:JVM 上的性能模型非常复杂,有时甚至不稳定.从微基准测试推断,即使它们是在所有应有的注意下完成的,也可能导致对生产系统性能的危险错误预测.
The main takeaway from this should be: the performance model on the JVM is highly complex, sometimes even erratic. Extrapolating from microbenchmarks, even when they are done with all due care, can lead to dangerously wrong predictions about production system performance.
这篇关于Java - Vector vs ArrayList 性能 - 测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!