免责声明: 我已经看过 此 的问题这个问题 但他们都得脱轨,通过小 详细信息和通 优化的,是不必要的问题。我真正需要的所有性能我 可以得到我的当前应用程序,这是 接收处理喷涌的MIDI数据 在实时。还需要扩大规模 以及可能的。

我比较 array 性能上的大量读于小型列出来 ArrayList 并且还只是具有的变量。我发现这一系列节拍 ArrayList 2.5个系数和 甚至是跳只是具有象引用。

我想知道的是:

  1. 是我的基准,好吗? 我已经换了测试和运行次数没有变化.我还用毫秒,而不是纳秒都无济于事。
  2. 我应该指定任何Java选项,尽量减少这种差异?
  3. 如果这种差异是真实的,在这种情况下 我不喜欢 Test[]ArrayList<Test> 在这种情况下,把在码需要将他们吗? 显然我读很多书写。

JVM Java1.6.0_17在OS x和它肯定是在运行中的热点模式。

  public class ArraysVsLists {

    static int RUNS = 100000;

    public static void main(String[] args) {
        long t1;
        long t2;

        Test test1 = new Test();
        test1.thing = (int)Math.round(100*Math.random());
        Test test2 = new Test();
        test2.thing = (int)Math.round(100*Math.random());

        t1 = System.nanoTime();

        for (int i=0; i<RUNS; i++) {
            test1.changeThing(i);
            test2.changeThing(i);
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1) + " How long NO collection");

        ArrayList<Test> list = new ArrayList<Test>(1);
        list.add(test1);
        list.add(test2);
        // tried this too: helps a tiny tiny bit 
        list.trimToSize();

        t1= System.nanoTime();

        for (int i=0; i<RUNS; i++) {
            for (Test eachTest : list) {
                eachTest.changeThing(i);
            }
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1) + " How long collection");


        Test[] array = new Test[2];
        list.toArray(array);

        t1= System.nanoTime();

        for (int i=0; i<RUNS; i++) {
            for (Test test : array) {
                test.changeThing(i);
            }
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1) + " How long array ");

    }
}

class Test {
    int thing;
    int thing2;
    public void changeThing(int addThis) {
        thing2 = addThis + thing;
    }
}
有帮助吗?

解决方案

微基准测试是非常,非常难以获得正确的平台喜欢Java。你肯定已经取代码基准入单独的方法、运行他们几千倍的热身,然后测量。我做了那(代码下面)以及结果是,直接通过引用的是后三次尽快通过的一个阵列,但是收集仍然是缓慢的一个因素2.

这些数字是基于JVM的选择 -server -XX:+DoEscapeAnalysis.没有 -server, 使用集合 大幅 慢(但奇怪的是,直接和一系列的访问是很快一点,表示有一些奇怪的会上)。 -XX:+DoEscapeAnalysis 产生的另一个30%的加速收集,但很多questionabled是否会的工作,以及对实际生产的代码。

总的我的结论是:忘了微基准测试,他们可以很容易被误导。衡量接近以产品代码为你可以没有必要重写你的整个应用程序。

import java.util.ArrayList;

public class ArrayTest {

    static int RUNS_INNER = 1000;
    static int RUNS_WARMUP = 10000;
    static int RUNS_OUTER = 100000;

    public static void main(String[] args) {
        long t1;
        long t2;

        Test test1 = new Test();
        test1.thing = (int)Math.round(100*Math.random());
        Test test2 = new Test();
        test2.thing = (int)Math.round(100*Math.random());

        for(int i=0; i<RUNS_WARMUP; i++)
        {
            testRefs(test1, test2);            
        }
        t1 = System.nanoTime();
        for(int i=0; i<RUNS_OUTER; i++)
        {
            testRefs(test1, test2);            
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1)/1000000.0 + " How long NO collection");

        ArrayList<Test> list = new ArrayList<Test>(1);
        list.add(test1);
        list.add(test2);
        // tried this too: helps a tiny tiny bit 
        list.trimToSize();

        for(int i=0; i<RUNS_WARMUP; i++)
        {
            testColl(list);
        }
        t1= System.nanoTime();

        for(int i=0; i<RUNS_OUTER; i++)
        {
            testColl(list);
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1)/1000000.0 + " How long collection");


        Test[] array = new Test[2];
        list.toArray(array);

        for(int i=0; i<RUNS_WARMUP; i++)
        {
            testArr(array);            
        }
        t1= System.nanoTime();

        for(int i=0; i<RUNS_OUTER; i++)
        {
            testArr(array);
        }

        t2 = System.nanoTime();
        System.out.println((t2-t1)/1000000.0 + " How long array ");

    }

    private static void testArr(Test[] array)
    {
        for (int i=0; i<RUNS_INNER; i++) {
            for (Test test : array) {
                test.changeThing(i);
            }
        }
    }

    private static void testColl(ArrayList<Test> list)
    {
        for (int i=0; i<RUNS_INNER; i++) {
            for (Test eachTest : list) {
                eachTest.changeThing(i);
            }
        }
    }

    private static void testRefs(Test test1, Test test2)
    {
        for (int i=0; i<RUNS_INNER; i++) {
            test1.changeThing(i);
            test2.changeThing(i);
        }
    }
}

class Test {
    int thing;
    int thing2;
    public void changeThing(int addThis) {
        thing2 = addThis + thing;
    }
}

其他提示

你的基准,才有效,如果实际使用情况相匹配的基准代码,即很少几个操作上的每一个元素,以便执行时间在很大程度上决定访问的时间,而不是操作自己。如果是这种情况,那么是的,你应该使用数组如果性能是至关重要的。然而,如果你真正的使用情况涉及到大量更多的实际计算每件,然后访问时间为每件将成为很多较不显着。

它可能是无效的。如果我理解的方式,即编译工作,编制一个方法不会影响到一个电话到这种方法已经执行。由于 main 方法只是所谓的一次,它将最终被解释,并且由于大多数工作是在体的方法,这个数字你不会特别指示的正常执行。

JIT汇编的效果可能有助于解释为什么没有收集的情况是速度较慢,该阵列的情况。这种结果是违反直觉的,它的地方一个怀疑上的其他基准结果的报告。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top