2

If I run this program the output is:

init: 1239.0
toCharArray: 1343.6
arraycopy: 1583.8

The first question is:
Why init() is faster than toCharArray()? Is there a compiler optimization here? (I am using Java 1.8.0_20)

The second question is:
Why toCharArray() is faster than arraycopy()? I copied arraycopy() from here: String.toCharArray().

public class MyClass {

    private static char[] SRC = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };

    public static void main(String[] args) {
        long start = 0;
        int init = 0, toCharArray = 0, arraycopy = 0;
        for (int j = 0; j < 5; j++) {
            start = System.currentTimeMillis();
            for (int i = 0; i < 100000000; i++)
                init();
            init += (System.currentTimeMillis() - start);

            start = System.currentTimeMillis();
            for (int i = 0; i < 100000000; i++)
                toCharArray();
            toCharArray += (System.currentTimeMillis() - start);

            start = System.currentTimeMillis();
            for (int i = 0; i < 100000000; i++)
                arraycopy();
            arraycopy += (System.currentTimeMillis() - start);
        }
        System.out.println("init: " + init / 5.0);
        System.out.println("toCharArray: " + toCharArray / 5.0);
        System.out.println("arraycopy: " + arraycopy / 5.0);
    }

    private static void init() {
        char[] c = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
        doSomething(c);
    }

    private static void toCharArray() {
        char[] c = "abcdefg".toCharArray();
        doSomething(c);
    }

    private static void arraycopy() {
        char[] c = new char[SRC.length];
        System.arraycopy(SRC, 0, c, 0, SRC.length);
        doSomething(c);
    }

    private static void doSomething(char[] c) {
        for (int i = 0; i < c.length; i++)
            c[i] = ' ';
    }

}

EDIT

Caliper result:

init:        min=11.90, 1st qu.=12.27, median=12.48, mean=12.44, 3rd qu.=12.54, max=13.16
toCharArray: min=13.10, 1st qu.=13.21, median=13.39, mean=13.49, 3rd qu.=13.78, max=14.27
arraycopy:   min=15.42, 1st qu.=15.49, median=15.51, mean=15.51, 3rd qu.=15.55, max=15.58
Krayo
  • 2,492
  • 4
  • 27
  • 45
  • 6
    These results can be ignored as you haven't warmed the JVM. Either learn how to microbench Java or use a testing library like Caliper. – Boris the Spider Sep 19 '14 at 22:49
  • Yup, test is flawed, if you switch toCharArray() and arraycopy() around I bet the results will be different – Steve Kuo Sep 19 '14 at 23:03
  • I changed the order: arraycopy: 1584.2 toCharArray: 1364.0. But thanks for the tip, I will try Caliper! – Krayo Sep 19 '14 at 23:13

2 Answers2

2

For "abcdefg".toCharArray(), String.toCharArray()'s source code is

public char[] toCharArray() {
    char result[] = new char[count];
    getChars(0, count, result, 0);
    return result;
}

getChars calls System.arraycopy so its performance with your arraycopy() should be the same. However, String's getChars copies from its internal char[] field, which is declared as final

private final char value[];

Where as your arraycopy() copies from SRC, which is non-final

private static char[] SRC = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };

This is just a guess, but trying making SRC final and see what happens.

Steve Kuo
  • 61,876
  • 75
  • 195
  • 257
  • You're right! After I make SRC final the result is: toCharArray: 1332.2 arraycopy: 1322.6. Thanks! So here is optimization. And do you have any idea why `init()` a bit faster than others? – Krayo Sep 20 '14 at 06:48
0

My first guess for my first question was the following:

I thought that the difference between init() and toCharArray() is that the init() skips array initialization with default values. But then I checked the bytecode and I haven't seen any difference.

Later I found this, and when I modified my test to work with a larger array, I realized that toCharArray() is faster!

To my second question I got the answer (thanks again).

Community
  • 1
  • 1
Krayo
  • 2,492
  • 4
  • 27
  • 45