Jump to page: 1 2
Thread overview
Why Java (server VM) is faster than D?
Aug 03, 2015
aki
Aug 03, 2015
John Colvin
Aug 03, 2015
Dmitry Olshansky
Aug 03, 2015
John Colvin
Aug 03, 2015
Adam D. Ruppe
Aug 03, 2015
John Colvin
Aug 03, 2015
aki
Aug 03, 2015
Etienne Cimon
Aug 03, 2015
Justin Whear
Aug 03, 2015
Iain Buclaw
Aug 03, 2015
John Colvin
Aug 03, 2015
Adam D. Ruppe
Aug 03, 2015
John Colvin
Aug 03, 2015
Dmitry Olshansky
Aug 03, 2015
Dmitry Olshansky
Aug 03, 2015
Adam D. Ruppe
August 03, 2015
When I was trying to port some Java program to D,
I noticed Java is faster than D.
I made a simple bench mark test as follows.
Then, I was shocked with the result.

test results on Win8 64bit (smaller is better)
Java(1.8.0,64bit,server): 0.677
C++(MS vs2013): 2.141
C#(MS vs2013): 2.220
D(DMD 2.067.1): 2.448
D(GDC 4.9.2/2.066): 2.481
Java(1.8.0,32bit,client): 3.060

Does anyone know the magic of Java?

Thanks, Aki.

---

test program for D lang:
import std.datetime;
import std.stdio;
class Foo {
	int i = 0;
	void bar() {}
};
class SubFoo : Foo {
	override void bar() {
		i = i * 3 + 1;
	}
};
int test(Foo obj, int repeat) {
	for (int r = 0; r<repeat; ++r) {
		obj.bar();
	}
	return obj.i;
}
void main() {
	auto stime = Clock.currTime();
	int repeat = 1000 * 1000 * 1000;
	int ret = test(new SubFoo(), repeat);
	double time = (Clock.currTime() - stime).total!"msecs" / 1000.0;
	writefln("time=%5.3f, ret=%d", time, ret);
}

test program for Java:
class Foo {
	public int i = 0;
	public void bar() {}
};
class SubFoo extends Foo {
	public void bar() {
		i = i * 3 + 1;
	}
};
public class Main {
	public static int test(Foo obj, int repeat) {
		for (int r = 0; r<repeat; ++r) {
			obj.bar();
		}
		return obj.i;
	}
	public static void main(String[] args) {
		long stime = System.currentTimeMillis();
		int repeat = 1000 * 1000 * 1000;
		int ret = test(new SubFoo(), repeat);
		double time = (System.currentTimeMillis() - stime) / 1000.0;
		System.out.printf("time=%5.3f, ret=%d", time, ret);
	}
}

August 03, 2015
On Monday, 3 August 2015 at 16:27:39 UTC, aki wrote:
> When I was trying to port some Java program to D,
> I noticed Java is faster than D.
> I made a simple bench mark test as follows.
> Then, I was shocked with the result.
>
> [...]

What compilation flags?
August 03, 2015
On 03-Aug-2015 19:27, aki wrote:
> When I was trying to port some Java program to D,
> I noticed Java is faster than D.
> I made a simple bench mark test as follows.
> Then, I was shocked with the result.
>
> test results on Win8 64bit (smaller is better)
> Java(1.8.0,64bit,server): 0.677
> C++(MS vs2013): 2.141
> C#(MS vs2013): 2.220
> D(DMD 2.067.1): 2.448
> D(GDC 4.9.2/2.066): 2.481
> Java(1.8.0,32bit,client): 3.060
>
> Does anyone know the magic of Java?
>
> Thanks, Aki.
>

Devirtualization? HotSpot is fairly aggressive in that regard.


-- 
Dmitry Olshansky
August 03, 2015
Java being fastest at running Java-style code is not too surprising.  My guess is that Java is "hotspot" inlining the calls to `bar`, getting rid of the dynamic dispatch overhead.  I think that for real systems D will generally beat out Java across the board, but not if the D version is a straight up transliteration of the Java--expect Java to be the best at running Java code.
August 03, 2015
On 3 August 2015 at 18:27, aki via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> When I was trying to port some Java program to D,
> I noticed Java is faster than D.
> I made a simple bench mark test as follows.
> Then, I was shocked with the result.
>
> test results on Win8 64bit (smaller is better)
> Java(1.8.0,64bit,server): 0.677
> C++(MS vs2013): 2.141
> C#(MS vs2013): 2.220
> D(DMD 2.067.1): 2.448
> D(GDC 4.9.2/2.066): 2.481
> Java(1.8.0,32bit,client): 3.060
>
> Does anyone know the magic of Java?
>
> Thanks, Aki.
>
>
I have read somewhere (or maybe heard) that Java VM is able to cache and possibly remove/inline dynamic dispatches on the fly.  This is a clear win for VM languages over native compiled.

Iain.


August 03, 2015
On Monday, 3 August 2015 at 16:27:39 UTC, aki wrote:
> When I was trying to port some Java program to D,
> I noticed Java is faster than D.
> I made a simple bench mark test as follows.
> Then, I was shocked with the result.
>
> test results on Win8 64bit (smaller is better)
> Java(1.8.0,64bit,server): 0.677
> C++(MS vs2013): 2.141
> C#(MS vs2013): 2.220
> D(DMD 2.067.1): 2.448
> D(GDC 4.9.2/2.066): 2.481
> Java(1.8.0,32bit,client): 3.060
>
> Does anyone know the magic of Java?
>
> Thanks, Aki.
>
> ---
>
> test program for D lang:
> import std.datetime;
> import std.stdio;
> class Foo {
> 	int i = 0;
> 	void bar() {}
> };
> class SubFoo : Foo {
> 	override void bar() {
> 		i = i * 3 + 1;
> 	}
> };
> int test(Foo obj, int repeat) {
> 	for (int r = 0; r<repeat; ++r) {
> 		obj.bar();
> 	}
> 	return obj.i;
> }
> void main() {
> 	auto stime = Clock.currTime();
> 	int repeat = 1000 * 1000 * 1000;
> 	int ret = test(new SubFoo(), repeat);
> 	double time = (Clock.currTime() - stime).total!"msecs" / 1000.0;
> 	writefln("time=%5.3f, ret=%d", time, ret);
> }
>
> test program for Java:
> class Foo {
> 	public int i = 0;
> 	public void bar() {}
> };
> class SubFoo extends Foo {
> 	public void bar() {
> 		i = i * 3 + 1;
> 	}
> };
> public class Main {
> 	public static int test(Foo obj, int repeat) {
> 		for (int r = 0; r<repeat; ++r) {
> 			obj.bar();
> 		}
> 		return obj.i;
> 	}
> 	public static void main(String[] args) {
> 		long stime = System.currentTimeMillis();
> 		int repeat = 1000 * 1000 * 1000;
> 		int ret = test(new SubFoo(), repeat);
> 		double time = (System.currentTimeMillis() - stime) / 1000.0;
> 		System.out.printf("time=%5.3f, ret=%d", time, ret);
> 	}
> }

Not surprising. The virtual function call takes almost all of the time and the JVM will be devirtualising it. If you want to call tiny virtual functions in tight loops, use a VM.

That said, it's a bit disappointing that the devirtualisation doesn't happen at compile-time after inlining for a simple case like this.
August 03, 2015
On 8/3/15 12:31 PM, Dmitry Olshansky wrote:
> On 03-Aug-2015 19:27, aki wrote:
>> When I was trying to port some Java program to D,
>> I noticed Java is faster than D.
>> I made a simple bench mark test as follows.
>> Then, I was shocked with the result.
>>
>> test results on Win8 64bit (smaller is better)
>> Java(1.8.0,64bit,server): 0.677
>> C++(MS vs2013): 2.141
>> C#(MS vs2013): 2.220
>> D(DMD 2.067.1): 2.448
>> D(GDC 4.9.2/2.066): 2.481
>> Java(1.8.0,32bit,client): 3.060
>>
>> Does anyone know the magic of Java?
>>
>> Thanks, Aki.
>>
>
> Devirtualization? HotSpot is fairly aggressive in that regard.

Yeah, I think that's it. virtual calls cannot be inlined by the D compiler, but could be inlined by hotspot. You can fix this by making the derived class final, or marking the method final, and always using a reference to the derived type. If you need virtualization still, you will have to deal with lower performance.

-Steve

August 03, 2015
You can try a few potential optimizations in the D version yourself and see if it makes a difference.

Devirtualization has a very small impact. Test this by making `test` take `SubFoo` and making `bar` final, or making `bar` a stand-alone function.

That's not it.

Inlining alone doesn't make a huge difference either - test this by copy/pasting the `bar` method body to the test function.

But we can see a *huge* difference if we inline AND make the data local:

int test(SubFoo obj, int repeat) {
        int i = obj.i; // local variable copy
        for (int r = 0; r<repeat; ++r) {
                //obj.bar();
                i = i *3 + 1; // do the math on the local
        }
        obj.i = i; // save it back to the object so same result to the outside
world
        return obj.i;
}



That cuts the time to less than 1/2 on my computer from the other fastest version.

So I suspect the JVM is able to figure out that the `i` member is being used and putting it in a hot cache instead of accessing it indirectly though the object, just like I did by hand there.

I betcha if the loop ran 5 times, it would be no different, but the JVM realizes after hundreds of iterations that there's a huge optimization potential there and rewrites the code at that point, making it faster for the next million runs.
August 03, 2015
On Monday, 3 August 2015 at 16:41:42 UTC, Steven Schveighoffer wrote:
> On 8/3/15 12:31 PM, Dmitry Olshansky wrote:
>> On 03-Aug-2015 19:27, aki wrote:
>>> When I was trying to port some Java program to D,
>>> I noticed Java is faster than D.
>>> I made a simple bench mark test as follows.
>>> Then, I was shocked with the result.
>>>
>>> test results on Win8 64bit (smaller is better)
>>> Java(1.8.0,64bit,server): 0.677
>>> C++(MS vs2013): 2.141
>>> C#(MS vs2013): 2.220
>>> D(DMD 2.067.1): 2.448
>>> D(GDC 4.9.2/2.066): 2.481
>>> Java(1.8.0,32bit,client): 3.060
>>>
>>> Does anyone know the magic of Java?
>>>
>>> Thanks, Aki.
>>>
>>
>> Devirtualization? HotSpot is fairly aggressive in that regard.
>
> Yeah, I think that's it. virtual calls cannot be inlined by the D compiler, but could be inlined by hotspot. You can fix this by making the derived class final, or marking the method final, and always using a reference to the derived type. If you need virtualization still, you will have to deal with lower performance.
>
> -Steve

Yup. I get very similar numbers to aki for his version, but changing two lines:

final class SubFoo : Foo {

int test(F)(F obj, int repeat) {

or less generally:

int test(SubFoo obj, int repeat) {

gets me down to 0.182s with ldc on OS X
August 03, 2015
On Monday, 3 August 2015 at 16:47:14 UTC, Adam D. Ruppe wrote:
> You can try a few potential optimizations in the D version yourself and see if it makes a difference.
>
> Devirtualization has a very small impact. Test this by making `test` take `SubFoo` and making `bar` final, or making `bar` a stand-alone function.
>
> That's not it.

Making SubFoo a final class and test take SubFoo gives a >10x speedup for me.
« First   ‹ Prev
1 2