RFR: 8155600 - Performance optimization of Arrays.asList().iterator()

Tagir F. Valeev amaembo at gmail.com
Thu Apr 28 07:37:10 UTC 2016


Hello!

Please review and sponsor the following patch:
https://bugs.openjdk.java.net/browse/JDK-8155600
http://cr.openjdk.java.net/~tvaleev/webrev/8155600/r1/

It appears that custom implementation of Arrays.asList().iterator() is
noticeably more performant than the AbstractList implementation used
currently. Here's JMH test which illustrates this:

http://cr.openjdk.java.net/~tvaleev/webrev/8155600/jmh/

    @Benchmark
    public int sumList() {
        return sum(list);
    }

    @Benchmark
    public int sumArray() {
        return sum(Arrays.asList(arr));
    }

    public static int sum(Iterable<Integer> data) {
        int sum = 0;
        for (int item : data) sum+=item;
        return sum;
    }

Here's summary result on my Intel x64 machine:

JDK 9ea+115:
Benchmark           (limit)  Mode  Cnt     Score    Error  Units
ArrayTest.sumArray        0  avgt   50     6,371 ±  0,009  ns/op
ArrayTest.sumArray        1  avgt   50     8,020 ±  0,100  ns/op
ArrayTest.sumArray       10  avgt   50    14,424 ±  0,060  ns/op
ArrayTest.sumArray      100  avgt   50    88,684 ±  3,261  ns/op
ArrayTest.sumArray     1000  avgt   50   677,048 ±  1,050  ns/op
ArrayTest.sumArray    10000  avgt   50  8038,224 ± 59,678  ns/op
ArrayTest.sumList         0  avgt   50     3,395 ±  0,003  ns/op
ArrayTest.sumList         1  avgt   50     5,613 ±  0,061  ns/op
ArrayTest.sumList        10  avgt   50    13,448 ±  0,076  ns/op
ArrayTest.sumList       100  avgt   50    97,242 ±  0,105  ns/op
ArrayTest.sumList      1000  avgt   50   664,342 ±  0,704  ns/op
ArrayTest.sumList     10000  avgt   50  7971,230 ± 61,344  ns/op

JDK 9ea+115 patched:
Benchmark           (limit)  Mode  Cnt     Score    Error  Units
ArrayTest.sumArray        0  avgt   50     2,932 ±  0,011  ns/op
ArrayTest.sumArray        1  avgt   50     5,000 ±  0,062  ns/op
ArrayTest.sumArray       10  avgt   50     9,421 ±  0,219  ns/op
ArrayTest.sumArray      100  avgt   50    43,848 ±  0,187  ns/op
ArrayTest.sumArray     1000  avgt   50   383,619 ±  1,019  ns/op
ArrayTest.sumArray    10000  avgt   50  6860,087 ± 13,022  ns/op
ArrayTest.sumList         0  avgt   50     3,400 ±  0,008  ns/op
ArrayTest.sumList         1  avgt   50     6,142 ±  0,047  ns/op
ArrayTest.sumList        10  avgt   50    12,488 ±  0,084  ns/op
ArrayTest.sumList       100  avgt   50    83,029 ±  0,078  ns/op
ArrayTest.sumList      1000  avgt   50   605,651 ±  0,992  ns/op
ArrayTest.sumList     10000  avgt   50  7649,681 ± 16,355  ns/op

AbstractList.iterator() makes unnecessary bookkeeping like modCount
tracking which reduces the performance. Also it seems that having
implicit this$0 field in AbstractList.iterator() makes impossible to
avoid allocation of short-lived Arrays.ArrayList object in sumArray()
test. Launching JMH -prof gc confirms that non-patched sumArray() test
allocates 24 bytes per invocation while patched sumArray() does not
allocate anything.

What do you think? Is it reasonable change? Should I check some tests
or add new ones for this optimization?

With best regards,
Tagir Valeev.




More information about the core-libs-dev mailing list