A HotSpot oddity

2 views
Skip to first unread message

David Pollak

unread,
Nov 30, 2007, 5:49:47 PM11/30/07
to jvm-la...@googlegroups.com
I've got the following Scala code:
object Foo {
  def main(argv: Array[String]) {
    var bits = 0L
    val start = System.currentTimeMillis()
    var n = 2000000001
    // var n = 2000000001L // makes things very slow
    while (n > 0) {
      bits = bits ^ (1 << 5)
      n = n - 1
    }
    System.out.println(bits)
    val end = System.currentTimeMillis()
    System.out.println(end-start)
  }
}

I'm enclosing the source and the bytecode.

There are 2B iterations.

On my Core 2 Quad running JDK 1.6 (32 bit), the code takes 2 ms to run.

On my Mac Book Pro (Core Duo, JDK 1.5) it takes 6,600 ms.

The run time on the Mac seems more "reasonable".  What's going on?



--
lift, the secure, simple, powerful web framework http://liftweb.net
Collaborative Task Management http://much4.us
wierd.zip

Erik Engbrecht

unread,
Nov 30, 2007, 6:18:26 PM11/30/07
to jvm-la...@googlegroups.com
David,
For me 1.5 and 1.6 perform about the same...1.6 is a little faster.  However, -server yields the surprisingly fast results that you are seeing under 1.6 and -client yields the slow results that you are seeing under 1.5.

It still doesn't explain why it's so fast...but it's another data point.  I'm using an ancient computer with Linux.

-Erik
--
http://erikengbrecht.blogspot.com/

David MacIver

unread,
Nov 30, 2007, 8:12:10 PM11/30/07
to jvm-la...@googlegroups.com

David MacIver

unread,
Nov 30, 2007, 8:13:27 PM11/30/07
to jvm-la...@googlegroups.com
For what it's worth, the obvious Java translation does the same thing:

class Foo{
public static void main(String[] args){
long bits = 0L;
long start = System.currentTimeMillis();
int n = 2000000001;
while (n > 0) {
bits ^= (1 << 5);
n--;
}
System.out.println(bits);
long end = System.currentTimeMillis();
System.out.println(end-start);

}
}

So it isn't a quirk of the bytecode scala produces


On Nov 30, 2007 11:18 PM, Erik Engbrecht <erik.en...@gmail.com> wrote:

David Pollak

unread,
Nov 30, 2007, 10:18:50 PM11/30/07
to jvm-la...@googlegroups.com
Yeah, the Scala code was a port of Java code that does similar things.  With the Scala command line and some other Scala tools, it's much faster to make a change and test the change with Scala than with Java.

Charles Oliver Nutter

unread,
Dec 1, 2007, 12:01:06 AM12/1/07
to jvm-la...@googlegroups.com
David Pollak wrote:
> On my Core 2 Quad running JDK 1.6 (32 bit), the code takes 2 ms to run.
>
> On my Mac Book Pro (Core Duo, JDK 1.5) it takes 6,600 ms.
>
> The run time on the Mac seems more "reasonable". What's going on?

If the core 2 is a server-class machine it will run the server VM by
default, which may be able to optimize much of the code away. Do you get
the same results forcing server or client VMs on both machines?

- Charlie

David MacIver

unread,
Dec 1, 2007, 5:53:15 AM12/1/07
to jvm-la...@googlegroups.com
More interesting data points:

On a 64-bit machine running linux there's no difference between the
client and server times. I don't know whether this is because the
64-bit client and server VM optimisations aren't as different as they
are in 32-bit mode or whether there's some advantage to 64-bit here
(if there is, gcc isn't taking advantage of it, see below).

The obvious C translation of

#include <stdio.h>

int main(){
long bits = 0L;


int n = 2000000001;
while (n > 0) {
bits ^= (1 << 5);
n--;
}

printf("%d", bits);
}

Seems to take longer than the client time, regardless of whether it's
in 64 or 32 bit mode.

Neil Bartlett

unread,
Dec 1, 2007, 6:02:27 AM12/1/07
to jvm-la...@googlegroups.com
"Scala faster than C" post to reddit, anyone? ;-)

David MacIver

unread,
Dec 1, 2007, 6:24:56 AM12/1/07
to jvm-la...@googlegroups.com
Surely it's no news that Java is competitive with C for pure numeric
operations.

David MacIver

unread,
Dec 1, 2007, 7:25:22 AM12/1/07
to jvm-la...@googlegroups.com
I think I've figured out what's going on. I can't figure out how to
get sufficient debug information out of the server hotspot to verify
this, but it seems to make sense and performing the translation
manually produces comparable speedups in the client VM.

class Foo{
public static void main(String[] args){
long bits = 0L;
long start = System.currentTimeMillis();
int n = 2000000001;
while (n > 0) {
bits ^= (1 << 5);
n--;
}
System.out.println(bits);
long end = System.currentTimeMillis();
System.out.println(end-start);

}

Unroll this loop by a factor of 2. So

while (n > 0) {
bits ^= (1 << 5);
n--;
}

becomes

while (n > 1) {


bits ^= (1 << 5);
n--;
bits ^= (1 << 5);
n--;
}

if (n == 1){


bits ^= (1 << 5);
n--;
}

Now we can reorder the unrolled loop as

while (n > 1) {
bits ^= (1 << 5) ^= (1 << 5);
n--;
n--;
}

But

bits ^= (1 << 5) ^= (1 << 5)

is the same as

bits ^= ( (1 << 5) ^ (1 << 5) )

Which is the same as

bits ^= 0

Which is bits = bits, a no-op.

So we can remove that calculation from the loop entirely.

So basically the reason the server VM is so freaking fast is that the
loop body is practically empty. :-) It's just the end result of a few
simple "throwing away uneccessary work" optimisations, nothing magic.

Richard Warburton

unread,
Dec 1, 2007, 11:17:13 AM12/1/07
to jvm-la...@googlegroups.com
> On a 64-bit machine running linux there's no difference between the
> client and server times. I don't know whether this is because the
> 64-bit client and server VM optimisations aren't as different as they
> are in 32-bit mode or whether there's some advantage to 64-bit here
> (if there is, gcc isn't taking advantage of it, see below).

I believe that the 64bit SUN JVM defaults to server mode. The
expectation is that 64bit things would be used on a server.

Richard Warburton

David MacIver

unread,
Dec 1, 2007, 11:31:31 AM12/1/07
to jvm-la...@googlegroups.com

I tried it with the -client flag as well. So it may not be a case of
default so much as "Always runs in server mode".

It would definitely explain some of the problems I've seen with Swing
on 64-bit VMs.

David MacIver

unread,
Dec 1, 2007, 11:33:35 AM12/1/07
to jvm-la...@googlegroups.com

And if I'd spent five minutes googling I would have discovered that
this is indeed the case. Doh.

Reply all
Reply to author
Forward
0 new messages