Question

I have two array of the same size and two methods.

public class Client {
    private static int[] ints;
    private static final int COUNT = 10000000;
    private static Integer[] integers;

    public static void main(String[] args) {
        Random rand = new Random();
        integers = new Integer[COUNT];
        for (int i = 0; i < integers.length; i++) {
            integers[i] = rand.nextInt();
        }

        ints = new int[COUNT];
        for (int i = 0; i < ints.length; i++) {
            ints[i] = rand.nextInt();
        }

        primitiveToObject();
        objectsToPrimitiveToObject();
    }

    public static  void primitiveToObject() {
        long start = new Date().getTime();
        List<Integer> objects = new ArrayList<>(ints.length);
        for (int i = 0; i < ints.length; i++) {
            int value = ints[i] + 1;
            objects.add(value);          //Boxing
        }
        System.out.println("prim -> object = " + (new Date().getTime() - start));
    }

    public static void objectsToPrimitiveToObject() {
        long start = new Date().getTime();
        List<Integer> result= new ArrayList<>(integers.length);
        for (int i = 0; i < integers.length; i++) {
            int value = integers[i] + 1; //Unboxing
            result.add(value);           //Boxing
        }
        System.out.println("obj -> prim -> object = " + (new Date().getTime() - start));
    }
}

Why objectsToPrimitiveToObject() with boxing and unboxing works 10x time faster than primitiveToObject() without unboxing?

Était-ce utile?

La solution

I think it is an artefact of how you are benchmarking the code.

I have run the following benchmark using JVM 1.7.0_09 with -XX:+AggressiveOpts -XX:CompileThreshold=1:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Main {
    static final int COUNT = 1000000;
    static int[] ints = new int[COUNT];
    static Integer[] integers = new Integer[COUNT];

    static void primitiveToObject() {
        List<Integer> objects = new ArrayList<Integer>(ints.length);
        for (int i = 0; i < ints.length; i++) {
            int value = ints[i] + 1;
            objects.add(value);                    //boxing
        }
    }

    static void objectsToPrimitiveToObject() {
        List<Integer> result= new ArrayList<Integer>(integers.length);
        for (int i = 0; i < integers.length; i++) {
            int value = integers[i] + 1;           //unboxing
            result.add(value);                     //boxing
        }
    }

    public static void main(String[] args) {
        Random rand = new Random();
        for (int i = 0; i < COUNT; ++i) {
            int val = rand.nextInt();
            ints[i] = val;
            integers[i] = val;
        }
        for (int i = 0; i < 10; ++i) {
            long start_p = System.currentTimeMillis();
            for (int j = 0; j < 100; ++j) {
                primitiveToObject();
            }
            long end_p = System.currentTimeMillis();
            long start_o = System.currentTimeMillis();
            for (int j = 0; j < 100; ++j) {
                objectsToPrimitiveToObject();
            }
            long end_o = System.currentTimeMillis();
            System.out.printf("p2o:%d o2p2o:%d\n", end_p - start_p, end_o - start_o);
        }
    }
}

The results were as follows:

p2o:2043 o2p2o:818
p2o:709 o2p2o:748
p2o:670 o2p2o:756
p2o:675 o2p2o:742
p2o:679 o2p2o:750
p2o:700 o2p2o:757
p2o:738 o2p2o:733
p2o:706 o2p2o:786
p2o:684 o2p2o:752
p2o:676 o2p2o:799

As you can see, after the initial warm-up, primitiveToObject() is faster, as one might expect from a method that's doing less work.

For completeness, I've also tested this using JDK 6, and observed similar results.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top