Why does the String-casting loop have static overhead?

Background

I ran the code (located at the bottom) to measure the performance of an explicit downgrade of Java, and I came across what seems to me to be a bit of an anomaly ... or maybe two anomalies.

I already reviewed this thread in Java, but it seems that it was only about casting in general, and not about this specific phenomenon. This thread covered similar topics, and I don't need advice on premature optimization - I tune parts of my application for maximum performance, so this is a logical step.

Tests

Basically, I wanted to test downcasting performance compared to the method .toString()for objects that were Strings but were printed as Objects. So, I created String aand Object bwith equivalent contents, performed three cycles and timed them.

  • Loop 1 - ((String) b).toLowerCase();
  • Loop 2 - b.toString().toLowerCase();
  • and cycle 3 - a.toLowerCase().

Test results

(Measurements in milliseconds.)

   iters   |  Test Round  |  Loop 1  |  Loop 2  |  Loop 3
-----------|--------------|----------|----------|----------
50,000,000 |      1       |   3367   |   3166   |   3186
  Test A   |      2       |   3543   |   3158   |   3156
           |      3       |   3365   |   3155   |   3169
-----------|--------------|----------|----------|----------
 5,000,000 |      1       |    373   |    348   |    369
  Test B   |      2       |    373   |    348   |    370
           |      3       |    399   |    334   |    371
-----------|--------------|----------|----------|----------
  500,000  |      1       |    66    |    36    |    33
  Test C   |      2       |    71    |    36    |    41
           |      3       |    66    |    35    |    34
-----------|--------------|----------|----------|----------
  50,000   |      1       |    27    |     5    |     5
  Test D   |      2       |    27    |     6    |     5
           |      3       |    26    |     5    |     5
-----------|--------------|----------|----------|----------

Code used for tests

long t, iters = ...;

String a = "String", c;
Object b = "String";

t = System.currentTimeMillis();
for (int i = 0; i < iters; i++) {
    c = ((String) b).toLowerCase();
}
System.out.println(System.currentTimeMillis() - t);

t = System.currentTimeMillis();
for (int i = 0; i < iters; i++) {
    c = b.toString().toLowerCase();
}
System.out.println(System.currentTimeMillis() - t);

t = System.currentTimeMillis();
for (int i = 0; i < iters; i++) {
    c = a.toLowerCase();
}
System.out.println(System.currentTimeMillis() - t);

Finally the question

What I find most fascinating is that cycle 2 ( .toString()) seemed to perform the best of the three (especially in test B), which does not create an intuitive meaning. Why would a call .toString()be faster than already having an object String?

, , , . A D, 9 (27 * 1000 = 27000, 3000); , ?

- , ?

()

: Bruno Reis , . , "", . , .

5 000 000 ( ):

     50    1             java.lang.String::toLowerCase (472 bytes)
     50    2             java.lang.CharacterData::of (120 bytes)
     53    3             java.lang.CharacterDataLatin1::getProperties (11 bytes)
     53    4             java.lang.Character::toLowerCase (9 bytes)
     54    5             java.lang.CharacterDataLatin1::toLowerCase (39 bytes)
     67    6     n       java.lang.System::arraycopy (0 bytes)   (static)
     68    7             java.lang.Math::min (11 bytes)
     68    8             java.util.Arrays::copyOfRange (63 bytes)
     69    9             java.lang.String::toLowerCase (8 bytes)
     69   10             java.util.Locale::getDefault (13 bytes)
     70    1 %           Main::main @ 14 (175 bytes)
[GC 49088K->360K(188032K), 0.0007670 secs]
[GC 49448K->360K(188032K), 0.0024814 secs]
[GC 49448K->328K(188032K), 0.0005422 secs]
[GC 49416K->328K(237120K), 0.0007519 secs]
[GC 98504K->352K(237120K), 0.0122388 secs]
[GC 98528K->352K(327552K), 0.0005734 secs]
    595    1 %           Main::main @ -2 (175 bytes)   made not entrant
548 /****** Junk Loop ******/
    597    2 %           Main::main @ 61 (175 bytes)
[GC 196704K->356K(327552K), 0.0008460 secs]
[GC 196708K->388K(523968K), 0.0005100 secs]
343 /****** Loop 1 ******/
    939    2 %           Main::main @ -2 (175 bytes)   made not entrant
    940   11             java.lang.String::toString (2 bytes)
    940    3 %           Main::main @ 103 (175 bytes)
[GC 393092K->356K(523968K), 0.0036496 secs]
377 /****** Loop 2 ******/
   1316    3 %           Main::main @ -2 (175 bytes)   made not entrant
   1317    4 %           Main::main @ 145 (175 bytes)
[GC 393060K->332K(759680K), 0.0008326 secs]
320 /****** Loop 3 ******/
+5
2

, SO Java. , , JIT, HotSpot ..

http://www.ibm.com/developerworks/java/library/j-jtp02225/index.html.

, VM VM - (JVM , , - , VM- ) ..

GC , , GC ( Full GC ). - , , , , .

, "" JVM, JVM, , , ..

, SO, , Java, , , : - Java?

+7

.toString() , String?

, , Loop 2 Loop3. , . B , GC Loop 3, Loop 2. .

, , ( -) , , JIT . ( JVM ...)

+2

All Articles