Thread overview | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 03, 2015 Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aki | 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aki | 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aki | 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aki Attachments:
| 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aki | 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aki | 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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 Re: Why Java (server VM) is faster than D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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.
|
Copyright © 1999-2021 by the D Language Foundation