digitalmars.D.learn - Properties set/get huge speed difference?
- ephemeros <ephemeros gmail.com> Sep 15 2006
- "Unknown W. Brackets" <unknown simplemachines.org> Sep 15 2006
- ephemeros <ephemeros gmail.com> Sep 16 2006
- Dave <Dave_member pathlink.com> Sep 16 2006
- ephemeros <ephemeros gmail.com> Sep 16 2006
- %u <fuzzyTew gmail.com> Oct 09 2006
- Lars Ivar Igesund <larsivar igesund.net> Oct 09 2006
- Sean Kelly <sean f4.ca> Oct 09 2006
- Josh Stern <josh_usenet phadd.net> Oct 09 2006
- Sean Kelly <sean f4.ca> Oct 09 2006
- Josh Stern <josh_usenet_xx phadd.net> Oct 09 2006
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
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
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
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
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
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
%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
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
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
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
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








Josh Stern <josh_usenet_xx phadd.net>