0

Eclipse plugin PMD suggests me to use

str.charAt(0) == 'a'

instead of

str.startWith("a")

But I don't want to make code more complicated and I believe that java compilers are very smart and they improve performance of str.startWith("a") by converting it into str.charAt(0) == 'a' (or something similar).

Am I right?

Julien Bodin
  • 783
  • 3
  • 19
Dmytro Plekhotkin
  • 1,965
  • 2
  • 23
  • 47
  • IMHO, it is not a compiler's job. PMD(or other static analysis tools ) should do it. – Jayan May 17 '13 at 16:28
  • 1
    The compiler probably won't convert it but I doubt it will make a noticeable difference performance wise... – assylias May 17 '13 at 16:28
  • 1
    Actually, the first sample should be `str.length() > 0 && str.charAt(0) == 'a'` to be semantically equivalent to the second. – meriton May 17 '13 at 16:44
  • 2
    Forget what you *believe*. Did you *benchmark* both ways and see what the *numbers* say? – Nik Bougalis May 17 '13 at 16:53

2 Answers2

3

A quick micro benchmark shows that the two methods perform very similarly (each taking less than 5 nanoseconds on my standard desktop machine with hotspot 7).

So I would just ignore that suggestion and use whichever version of the code that feels more readable for you.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • Something tells me that posting here took the OP longer than it would have to run this little benchmark himself. Also, *hooray for numbers!* – Nik Bougalis May 17 '13 at 16:54
  • I wrote a little test method and then I invoked it in loop 10 million times. And charAt is faster by 4 times than startWith. But when number of invokations was increased to 1 billion charAt became faster by 700 times. – Dmytro Plekhotkin May 17 '13 at 17:24
  • 1
    @Dmytro Have you excluded JVM warmup from measurement? How do you measure the times? How do you exercise the methods? – assylias May 17 '13 at 17:54
  • @assylias just as described here (inside code): http://stackoverflow.com/questions/8423789/benchmarking-inside-java-code – Dmytro Plekhotkin May 18 '13 at 09:50
  • @Dmytro It is difficult to say without seeing your actual code. In particular, if you run everything within `main`, the order in which you run the tests probably has an impact on the result. Make also sure you actually use the result of `startsWith` or `charAt` otherwise the JIT will probably just optimise you whole test as a no-op. You also need to check for GC, compilation, inlining, etc. – assylias May 18 '13 at 15:13
3

Here is decompiled code with both methods from a Java 7 compiled class. No optimization was done for either method and should be safe to assume that a Java 6 compiler would perform any such optimization either:

Before:

String str = "abc";
if (str.charAt(0) == 'a') {
   System.out.println("Using CharAt");
}
if (str.startsWith("a")) {
   System.out.println("Using startsWith");
}

After:

String str = "abc";
if(str.charAt(0) == 'a')
    System.out.println("Using CharAt");
if(str.startsWith("a"))
    System.out.println("Using startsWith");
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • 1
    But always remember that the compilation to byte code is only the first place where optimizations may occur. It doesn't say anything about JIT optimizing at runtime. (I know: in the original question only the compilation to bytecode had been adressed) – mschenk74 May 17 '13 at 21:38