当前位置: 首页 > 面试题库 >

Java-向量与ArrayList性能-测试

田焕
2023-03-14
问题内容

大家都说,由于性能的原因,应该使用vector(因为Vector在每次操作和所有操作之后都会同步)。我写了一个简单的测试:

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在遍历和阅读方面的表现要好一些。也许这是一个愚蠢的任务,或者我做出了错误的假设-有人可以解释一下吗?


问题答案:

您已经编写了一个幼稚的微基准测试。在JVM上进行微基准测试是一项非常棘手的事情,要列举所有的陷阱甚至不容易,但是这里有一些经典的方法:

  1. 您必须预热代码;
  2. 您必须控制垃圾收集暂停;
  3. System.currentTimeMillis是不精确的,但您似乎甚至都不知道这种方法(您的方法new Date().getTime()是等效的,但速度较慢)。

如果要正确执行此操作,请查看Oracle的jmh工具或Google的Caliper。

我的测试结果

由于我很想亲自查看这些数字,因此这里是的输出jmh。一,测试代码:

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

这样做的主要收获应该是: JVM上的性能模型非常复杂,有时甚至是不稳定的
。从微观基准推断,即使在采取所有适当措施的情况下,也可能导致对生产系统性能的危险错误预测。



 类似资料:
  • 问题内容: 向量是同步的,ArrayList是不同步的,但是我们可以通过来同步ArrayList ,那么哪个会更好,更快地执行? 问题答案: 同步收集既浪费时间又危险。一个很简单的例子,为什么它们不好,是考虑两个线程在同一集合上同时运行一个循环: 我们的列表可能是同步的(例如,Vector),并且此代码仍然可怕地中断。为什么?因为对size(),get(),remove()的单个调用是同步的,但是

  • 任何软件都需要掌握其性能瓶颈,以及线上运行时的性能状态。Logstash 也不例外。 长久以来,Logstash 在这方面一直处于比较黑盒的状态。因为其内部队列使用的是标准的 stud 库,并非自己实现,在 Logstash 本身源代码里是找不出来什么问题的。我们只能按照其 pipeline 原理,总结出来一些模拟检测的手段。 在 Logstash-5.0.0 中,一大改进就是学习 Elastic

  • 过早优化,往往引来各种麻烦。 一项技术究竟能否实用,有两项基本指标十分关键:一是功能的完备;一是性能的达标。 本章将试图对已有区块链技术进行一些评测。所有结果将尽可能保证客观准确,但不保证评测方法是否科学、评测结果是否具备足够参考性。

  • 我正在尝试用Java编写一个程序,该程序将计算整数数组(具有5个元素)中的所有元素组合,并将这些组合输出到ArrayList。我在下面包含了我的代码。 我使用按位运算来查找组合。每个组合都构造为一个 ArrayList(Integer),称为“writeitem”。然后我想将它们存储在另一个名为“master”的ArrayList中,它必须具有ArrayList(ArrayList(Integer

  • 我们在Spring批处理块分区架构的基础上编写了一个批处理基础框架。(主从并行处理模型)[1]

  • 本文向大家介绍Java中ArrayList和LinkedList的遍历与性能分析,包括了Java中ArrayList和LinkedList的遍历与性能分析的使用技巧和注意事项,需要的朋友参考一下 前言 通过本文你可以了解List的五种遍历方式及各自性能和foreach及Iterator的实现,加深对ArrayList和LinkedList实现的了解。下面来一起看看吧。 一、List的五种遍历方式