Java - Vector vs ArrayList 性能 - 测试 [英] Java - Vector vs ArrayList performance - test

查看:23
本文介绍了Java - Vector vs ArrayList 性能 - 测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为性能的原因,每个人都说应该使用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:

  1. 你必须预热代码;
  2. 您必须控制垃圾收集暂停;
  3. System.currentTimeMillis 不精确,但您似乎甚至不知道这种方法(您的 new Date().getTime() 是等效的,但是较慢).
  1. you must warm up the code;
  2. you must control for garbage collection pauses;
  3. System.currentTimeMillis is imprecise, but you don't seem to be aware of even this method (your new 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 on Vector 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 of Vector 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆