www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Properties set/get huge speed difference?

reply ephemeros <ephemeros gmail.com> writes:
Hello,

anyone knows why getting/setting the class properties by invoking the 
methods is so slow (~20 times slower - gdc/ubuntu/amd32) comparing with 
doing the same things directly, with the "=" operator (public 
properties)? this matters in an app with thousands of evaluations per 
loop, also the methods are needed to compose different behaviors, etc.
i give here a little "get" example:

//=======================
// src/clasamare.d

module src.clasamare;

class ClasaMare
{
	//private:
	float val;
	
	//public:
	void value(float newValue)
	{
		val=newValue;
	}
	float value()
	{
		return val;
	}
}
//=========================

this runs slower(~0.450s):

//=========================
// src/test.d

import src.clasamare;
import std.cstream;

int main()
{
	ClasaMare cls1=new ClasaMare();
	for(uint i=0; i<100000000; i++)
	{
		cls1.value=15.7;
	}
	dout.writefln("%f", cls1.value);
	return 0;
}
//==========================

this is faster(~0.020s):

//=========================
// src/test.d

import src.clasamare;
import std.cstream;

int main()
{
	ClasaMare cls1=new ClasaMare();
	for(uint i=0; i<100000000; i++)
	{
		cls1.val=15.7;
	}
	dout.writefln("%f", cls1.value);
	return 0;
}
//==========================

i compiled with this command:

gdc -frelease -s -O3 -fomit-frame-pointer -mmmx -msse -mfpmath=sse 
-mfancy-math-387 -minline-all-stringops -fschedule-insns2 
-frerun-loop-opt -frerun-cse-after-loop -funroll-loops 
-fexpensive-optimizations -finline-functions -o made test.d 
src/clasamica.d src/clasamare.d

when i compile with:
gdmd -O -release -inline test.d src/clasamica.d src/clasamare.d
the times are 0.450s/0.150s

thank you
Sep 15 2006
parent reply "Unknown W. Brackets" <unknown simplemachines.org> writes:
Try defining the getter and setter as final.

It's a function call, and it's using a virtual table as far as I know. 
That's going to be a lot slower.

-[Unknown]


 Hello,
 
 anyone knows why getting/setting the class properties by invoking the 
 methods is so slow (~20 times slower - gdc/ubuntu/amd32) comparing with 
 doing the same things directly, with the "=" operator (public 
 properties)? this matters in an app with thousands of evaluations per 
 loop, also the methods are needed to compose different behaviors, etc.
 i give here a little "get" example:
 
 //=======================
 // src/clasamare.d
 
 module src.clasamare;
 
 class ClasaMare
 {
     //private:
     float val;
     
     //public:
     void value(float newValue)
     {
         val=newValue;
     }
     float value()
     {
         return val;
     }
 }
 //=========================
 
 this runs slower(~0.450s):
 
 //=========================
 // src/test.d
 
 import src.clasamare;
 import std.cstream;
 
 int main()
 {
     ClasaMare cls1=new ClasaMare();
     for(uint i=0; i<100000000; i++)
     {
         cls1.value=15.7;
     }
     dout.writefln("%f", cls1.value);
     return 0;
 }
 //==========================
 
 this is faster(~0.020s):
 
 //=========================
 // src/test.d
 
 import src.clasamare;
 import std.cstream;
 
 int main()
 {
     ClasaMare cls1=new ClasaMare();
     for(uint i=0; i<100000000; i++)
     {
         cls1.val=15.7;
     }
     dout.writefln("%f", cls1.value);
     return 0;
 }
 //==========================
 
 i compiled with this command:
 
 gdc -frelease -s -O3 -fomit-frame-pointer -mmmx -msse -mfpmath=sse 
 -mfancy-math-387 -minline-all-stringops -fschedule-insns2 
 -frerun-loop-opt -frerun-cse-after-loop -funroll-loops 
 -fexpensive-optimizations -finline-functions -o made test.d 
 src/clasamica.d src/clasamare.d
 
 when i compile with:
 gdmd -O -release -inline test.d src/clasamica.d src/clasamare.d
 the times are 0.450s/0.150s
 
 thank you

Sep 15 2006
parent reply ephemeros <ephemeros gmail.com> writes:
Unknown W. Brackets wrote:
 Try defining the getter and setter as final.
 
 It's a function call, and it's using a virtual table as far as I know. 
 That's going to be a lot slower.
 
 -[Unknown]
 
 

i tried, there is no notable difference. :(
Sep 16 2006
parent reply Dave <Dave_member pathlink.com> writes:
ephemeros wrote:
 Unknown W. Brackets wrote:
 Try defining the getter and setter as final.

 It's a function call, and it's using a virtual table as far as I know. 
 That's going to be a lot slower.

 -[Unknown]

i tried, there is no notable difference. :(

DMD does inline inter-module 'final'.
Sep 16 2006
parent reply ephemeros <ephemeros gmail.com> writes:
Dave wrote:
 ephemeros wrote:
 Unknown W. Brackets wrote:
 Try defining the getter and setter as final.

 It's a function call, and it's using a virtual table as far as I 
 know. That's going to be a lot slower.

 -[Unknown]

i tried, there is no notable difference. :(

DMD does inline inter-module 'final'.

although the program compiled with dmd is slower (0.20s) than gdc, this doesn't concern me now. "final" works in dmd, both gets/sets have the same speed. thanks guys!
Sep 16 2006
parent reply %u <fuzzyTew gmail.com> writes:
 although the program compiled with dmd is slower (0.20s) than gdc, this
 doesn't concern me now. "final" works in dmd, both gets/sets have the
 same speed.

I thought D was supposed to automatically make all methods final that aren't changed by a subclass?
Oct 09 2006
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
%u wrote:

 although the program compiled with dmd is slower (0.20s) than gdc, this
 doesn't concern me now. "final" works in dmd, both gets/sets have the
 same speed.

I thought D was supposed to automatically make all methods final that aren't changed by a subclass?

How could the compiler know that? The class might be put into a library, and subclassed in an application (a very common use case) or other library. -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Oct 09 2006
parent reply Sean Kelly <sean f4.ca> writes:
Lars Ivar Igesund wrote:
 %u wrote:
 
 although the program compiled with dmd is slower (0.20s) than gdc, this
 doesn't concern me now. "final" works in dmd, both gets/sets have the
 same speed.

I thought D was supposed to automatically make all methods final that aren't changed by a subclass?

How could the compiler know that? The class might be put into a library, and subclassed in an application (a very common use case) or other library.

I think it's more likely that a compiler may optimize function calls when it knows exactly what type of object is being called. For example: class C { void doSomething() {} } void main() { C c = new C(); c.doSomething(); // A } In the code above, even though a vtbl entry may be generated for doSomething, the compiler may optimize the call at point A by calling C.doSomething directly instead of using a double lookup through C's vtbl. This can be accomplished because the compiler knows that c must be an instance of C at the call point (thus making the optimization extensible to more complex cases where doSomething really is a virtual function). I'm not sure if DMD currently performs this optimization however, but my guess would be that it does not. It's still more important to make DMD as bug-free as possible than it is to optimize corner-cases. Sean
Oct 09 2006
parent reply Josh Stern <josh_usenet phadd.net> writes:
On Mon, 09 Oct 2006 12:20:36 -0700, Sean Kelly wrote:


      void main() {
          C c = new C();
          c.doSomething(); // A
      }
 
 In the code above, even though a vtbl entry may be generated for 
 doSomething, the compiler may optimize the call at point A by calling 
 C.doSomething directly instead of using a double lookup through C's 
 vtbl.  This can be accomplished because the compiler knows that c must 
 be an instance of C at the call point (thus making the optimization 
 extensible to more complex cases where doSomething really is a virtual 
 function).  I'm not sure if DMD currently performs this optimization 
 however, but my guess would be that it does not.  It's still more 
 important to make DMD as bug-free as possible than it is to optimize 
 corner-cases.

I had all the same thoughts. For all these reasons, wouldn't it be a good idea to add "final" methods to the language to give the developer the necessary tool to optimize this intelligently if they need it?
Oct 09 2006
parent reply Sean Kelly <sean f4.ca> writes:
Josh Stern wrote:
 On Mon, 09 Oct 2006 12:20:36 -0700, Sean Kelly wrote:
 
 
      void main() {
          C c = new C();
          c.doSomething(); // A
      }

 In the code above, even though a vtbl entry may be generated for 
 doSomething, the compiler may optimize the call at point A by calling 
 C.doSomething directly instead of using a double lookup through C's 
 vtbl.  This can be accomplished because the compiler knows that c must 
 be an instance of C at the call point (thus making the optimization 
 extensible to more complex cases where doSomething really is a virtual 
 function).  I'm not sure if DMD currently performs this optimization 
 however, but my guess would be that it does not.  It's still more 
 important to make DMD as bug-free as possible than it is to optimize 
 corner-cases.

I had all the same thoughts. For all these reasons, wouldn't it be a good idea to add "final" methods to the language to give the developer the necessary tool to optimize this intelligently if they need it?

Hrm... perhaps I'm misunderstanding, but don't they already exist? class C { final void doSomething() {} } 'final' guarantees that C.doSomething above will not have a vtbl entry. Sean
Oct 09 2006
parent Josh Stern <josh_usenet_xx phadd.net> writes:
On Mon, 09 Oct 2006 16:22:13 -0700, Sean Kelly wrote:

 Josh Stern wrote:
 On Mon, 09 Oct 2006 12:20:36 -0700, Sean Kelly wrote:


 I had all the same thoughts.  For all these reasons, wouldn't it be a good
 idea to add "final" methods to the language to give the developer the
 necessary tool to optimize this intelligently if they need it?

Hrm... perhaps I'm misunderstanding, but don't they already exist? class C { final void doSomething() {} } 'final' guarantees that C.doSomething above will not have a vtbl entry.

Excellent! I knew it *should* be there, but I got thrown off by the docs when it isn't mentioned on the "class" page and the first paragraph on the "function" page says that all member functions are virtual because the compiler can figure out if they really need to be (though we just discussed why that isn't true).
Oct 09 2006