www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Interface vs pure abstract class - speed.

reply "SundayMorningRunner" <someone somewhere.uk> writes:
Hello, let's say I have the choice between using an abstract 
class or an interface to declare a "plan", a "template" for the 
descendants.

 From the dmd compiler point of view, should I use the abstract 
class version (so I guess that for each method call, there will 
be a few MOV, in order to extract the relative address from the 
vmt before a CALL) or the interface version (are the CALL 
directly performed in this case). Are interface faster ? (to get 
the address used by the CALL).

Thx.
May 12 2013
next sibling parent reply "Diggory" <diggsey googlemail.com> writes:
On Sunday, 12 May 2013 at 17:31:22 UTC, SundayMorningRunner wrote:
 Hello, let's say I have the choice between using an abstract 
 class or an interface to declare a "plan", a "template" for the 
 descendants.

 From the dmd compiler point of view, should I use the abstract 
 class version (so I guess that for each method call, there will 
 be a few MOV, in order to extract the relative address from the 
 vmt before a CALL) or the interface version (are the CALL 
 directly performed in this case). Are interface faster ? (to 
 get the address used by the CALL).

 Thx.
I would expect abstract classes to be slightly faster (certainly they shouldn't be slower), but the difference to be insignificant compared to other factors. Deriving from an abstract base class is a much stronger relationship than implementing an interface, so it depends on your situation. If your class is a "provider" (eg. it provides some functionality such as being able to receive some event) then an interface makes more sense. If your class is a type of something (eg. a button is a type of gui control) then inheritance makes more sense.
May 12 2013
parent "SundayMorningRunner" <someone somewhere.com> writes:
On Sunday, 12 May 2013 at 18:00:10 UTC, Diggory wrote:
 On Sunday, 12 May 2013 at 17:31:22 UTC, SundayMorningRunner 
 wrote:
 Hello, let's say I have the choice between using an abstract 
 class or an interface to declare a "plan", a "template" for 
 the descendants.

 From the dmd compiler point of view, should I use the abstract 
 class version (so I guess that for each method call, there 
 will be a few MOV, in order to extract the relative address 
 from the vmt before a CALL) or the interface version (are the 
 CALL directly performed in this case). Are interface faster ? 
 (to get the address used by the CALL).

 Thx.
I would expect abstract classes to be slightly faster (certainly they shouldn't be slower), but the difference to be insignificant compared to other factors. Deriving from an abstract base class is a much stronger relationship than implementing an interface, so it depends on your situation. If your class is a "provider" (eg. it provides some functionality such as being able to receive some event) then an interface makes more sense. If your class is a type of something (eg. a button is a type of gui control) then inheritance makes more sense.
It's ok about the difference between an interface and an abstract class. My question is really technical: which is the fatest: to a method from an interface or to the overriden method of an abstract class ? Think about a context such as audio DSP, where a method will be called for each buffer during 2 or 3 hours without interuption, and maybe 3 or 4 times per second...
May 12 2013
prev sibling next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Sunday, 12 May 2013 at 17:31:22 UTC, SundayMorningRunner wrote:
 Hello, let's say I have the choice between using an abstract 
 class or an interface to declare a "plan", a "template" for the 
 descendants.
 From the dmd compiler point of view, should I use the abstract 
 class version (so I guess that for each method call, there will 
 be a few MOV, in order to extract the relative address from the 
 vmt before a CALL) or the interface version (are the CALL 
 directly performed in this case). Are interface faster ? (to 
 get the address used by the CALL).

 Thx.
I doubt that looking from buggy compiler POV is a good idea. Anyway you can take code and look into assembly.
May 12 2013
parent reply "SundayMorningRunner" <someone somewhere.com> writes:
On Sunday, 12 May 2013 at 18:14:51 UTC, Maxim Fomin wrote:
 On Sunday, 12 May 2013 at 17:31:22 UTC, SundayMorningRunner 
 wrote:
 Hello, let's say I have the choice between using an abstract 
 class or an interface to declare a "plan", a "template" for 
 the descendants.
 From the dmd compiler point of view, should I use the abstract 
 class version (so I guess that for each method call, there 
 will be a few MOV, in order to extract the relative address 
 from the vmt before a CALL) or the interface version (are the 
 CALL directly performed in this case). Are interface faster ? 
 (to get the address used by the CALL).

 Thx.
I doubt that looking from buggy compiler POV is a good idea. Anyway you can take code and look into assembly.
Which is exactly what you could have done before answering ;)
May 12 2013
parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Sunday, 12 May 2013 at 18:21:14 UTC, SundayMorningRunner wrote:
 On Sunday, 12 May 2013 at 18:14:51 UTC, Maxim Fomin wrote:
 On Sunday, 12 May 2013 at 17:31:22 UTC, SundayMorningRunner 
 wrote:
 Hello, let's say I have the choice between using an abstract 
 class or an interface to declare a "plan", a "template" for 
 the descendants.
 From the dmd compiler point of view, should I use the 
 abstract class version (so I guess that for each method call, 
 there will be a few MOV, in order to extract the relative 
 address from the vmt before a CALL) or the interface version 
 (are the CALL directly performed in this case). Are interface 
 faster ? (to get the address used by the CALL).

 Thx.
I doubt that looking from buggy compiler POV is a good idea. Anyway you can take code and look into assembly.
Which is exactly what you could have done before answering ;)
This is exactly what I *have done* before answering to get correct answer for me. I see no reasons to ask such questions if you can do the test yourself. interface I { void foo(); } class A : I { void foo(){}} abstract class B { void foo() {} } class C : B {} void bar(C c, I i) { c.foo(); i.foo(); } void main() { A a = new A; a.foo(); C c = new C; c.foo(); bar(c, a); } disas _Dmain Dump of assembler code for function _Dmain: 0x0000000000419cd8 <+0>: push %rbp 0x0000000000419cd9 <+1>: mov %rsp,%rbp 0x0000000000419cdc <+4>: sub $0x10,%rsp 0x0000000000419ce0 <+8>: movabs $0x639210,%rdi 0x0000000000419cea <+18>: callq 0x41becc <_d_newclass> 0x0000000000419cef <+23>: mov %rax,-0x10(%rbp) 0x0000000000419cf3 <+27>: mov %rax,%rdi 0x0000000000419cf6 <+30>: mov (%rax),%rcx 0x0000000000419cf9 <+33>: rex.W callq *0x28(%rcx) 0x0000000000419cfd <+37>: movabs $0x639380,%rdi 0x0000000000419d07 <+47>: callq 0x41becc <_d_newclass> 0x0000000000419d0c <+52>: mov %rax,-0x8(%rbp) 0x0000000000419d10 <+56>: mov %rax,%rdi 0x0000000000419d13 <+59>: mov (%rax),%rdx 0x0000000000419d16 <+62>: rex.W callq *0x28(%rdx) 0x0000000000419d1a <+66>: mov -0x8(%rbp),%rsi 0x0000000000419d1e <+70>: cmpq $0x0,-0x10(%rbp) 0x0000000000419d23 <+75>: je 0x419d2f <_Dmain+87> 0x0000000000419d25 <+77>: mov -0x10(%rbp),%rax 0x0000000000419d29 <+81>: lea 0x10(%rax),%rdi 0x0000000000419d2d <+85>: jmp 0x419d32 <_Dmain+90> 0x0000000000419d2f <+87>: xor %rdi,%rdi ---Type <return> to continue, or q <return> to quit--- 0x0000000000419d32 <+90>: callq 0x419cb0 <_D4main3barFC4main1CC4main1IZv> 0x0000000000419d37 <+95>: xor %eax,%eax 0x0000000000419d39 <+97>: leaveq 0x0000000000419d3a <+98>: retq End of assembler dump. disas _D4main3barFC4main1CC4main1IZv Dump of assembler code for function _D4main3barFC4main1CC4main1IZv: 0x0000000000419cb0 <+0>: push %rbp 0x0000000000419cb1 <+1>: mov %rsp,%rbp 0x0000000000419cb4 <+4>: sub $0x10,%rsp 0x0000000000419cb8 <+8>: mov %rdi,-0x10(%rbp) 0x0000000000419cbc <+12>: mov %rsi,%rdi 0x0000000000419cbf <+15>: mov (%rsi),%rax 0x0000000000419cc2 <+18>: rex.W callq *0x28(%rax) 0x0000000000419cc6 <+22>: mov -0x10(%rbp),%rdi 0x0000000000419cca <+26>: mov (%rdi),%rcx 0x0000000000419ccd <+29>: rex.W callq *0x8(%rcx) 0x0000000000419cd1 <+33>: leaveq 0x0000000000419cd2 <+34>: retq End of assembler dump.
May 12 2013
parent "D-Ratiseur" <someone somewhere.com> writes:
On Sunday, 12 May 2013 at 18:45:29 UTC, Maxim Fomin wrote:
 On Sunday, 12 May 2013 at 18:21:14 UTC, SundayMorningRunner 
 wrote:
 On Sunday, 12 May 2013 at 18:14:51 UTC, Maxim Fomin wrote:
 On Sunday, 12 May 2013 at 17:31:22 UTC, SundayMorningRunner 
 wrote:
 Hello, let's say I have the choice between using an abstract 
 class or an interface to declare a "plan", a "template" for 
 the descendants.
 From the dmd compiler point of view, should I use the 
 abstract class version (so I guess that for each method 
 call, there will be a few MOV, in order to extract the 
 relative address from the vmt before a CALL) or the 
 interface version (are the CALL directly performed in this 
 case). Are interface faster ? (to get the address used by 
 the CALL).

 Thx.
I doubt that looking from buggy compiler POV is a good idea. Anyway you can take code and look into assembly.
Which is exactly what you could have done before answering ;)
This is exactly what I *have done* before answering to get correct answer for me. I see no reasons to ask such questions if you can do the test yourself. interface I { void foo(); } class A : I { void foo(){}} abstract class B { void foo() {} } class C : B {} void bar(C c, I i) { c.foo(); i.foo(); } void main() { A a = new A; a.foo(); C c = new C; c.foo(); bar(c, a); } disas _Dmain Dump of assembler code for function _Dmain: 0x0000000000419cd8 <+0>: push %rbp 0x0000000000419cd9 <+1>: mov %rsp,%rbp 0x0000000000419cdc <+4>: sub $0x10,%rsp 0x0000000000419ce0 <+8>: movabs $0x639210,%rdi 0x0000000000419cea <+18>: callq 0x41becc <_d_newclass> 0x0000000000419cef <+23>: mov %rax,-0x10(%rbp) 0x0000000000419cf3 <+27>: mov %rax,%rdi 0x0000000000419cf6 <+30>: mov (%rax),%rcx 0x0000000000419cf9 <+33>: rex.W callq *0x28(%rcx) 0x0000000000419cfd <+37>: movabs $0x639380,%rdi 0x0000000000419d07 <+47>: callq 0x41becc <_d_newclass> 0x0000000000419d0c <+52>: mov %rax,-0x8(%rbp) 0x0000000000419d10 <+56>: mov %rax,%rdi 0x0000000000419d13 <+59>: mov (%rax),%rdx 0x0000000000419d16 <+62>: rex.W callq *0x28(%rdx) 0x0000000000419d1a <+66>: mov -0x8(%rbp),%rsi 0x0000000000419d1e <+70>: cmpq $0x0,-0x10(%rbp) 0x0000000000419d23 <+75>: je 0x419d2f <_Dmain+87> 0x0000000000419d25 <+77>: mov -0x10(%rbp),%rax 0x0000000000419d29 <+81>: lea 0x10(%rax),%rdi 0x0000000000419d2d <+85>: jmp 0x419d32 <_Dmain+90> 0x0000000000419d2f <+87>: xor %rdi,%rdi ---Type <return> to continue, or q <return> to quit--- 0x0000000000419d32 <+90>: callq 0x419cb0 <_D4main3barFC4main1CC4main1IZv> 0x0000000000419d37 <+95>: xor %eax,%eax 0x0000000000419d39 <+97>: leaveq 0x0000000000419d3a <+98>: retq End of assembler dump. disas _D4main3barFC4main1CC4main1IZv Dump of assembler code for function _D4main3barFC4main1CC4main1IZv: 0x0000000000419cb0 <+0>: push %rbp 0x0000000000419cb1 <+1>: mov %rsp,%rbp 0x0000000000419cb4 <+4>: sub $0x10,%rsp 0x0000000000419cb8 <+8>: mov %rdi,-0x10(%rbp) 0x0000000000419cbc <+12>: mov %rsi,%rdi 0x0000000000419cbf <+15>: mov (%rsi),%rax 0x0000000000419cc2 <+18>: rex.W callq *0x28(%rax) 0x0000000000419cc6 <+22>: mov -0x10(%rbp),%rdi 0x0000000000419cca <+26>: mov (%rdi),%rcx 0x0000000000419ccd <+29>: rex.W callq *0x8(%rcx) 0x0000000000419cd1 <+33>: leaveq 0x0000000000419cd2 <+34>: retq End of assembler dump.
so take a tip: go on home. so take a tip: you'll never beat the IRA.
May 12 2013
prev sibling parent Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
On 5/12/2013 12:31 PM, SundayMorningRunner wrote:
 Hello, let's say I have the choice between using an abstract class or an
 interface to declare a "plan", a "template" for the descendants.

  From the dmd compiler point of view, should I use the abstract class
 version (so I guess that for each method call, there will be a few MOV,
 in order to extract the relative address from the vmt before a CALL) or
 the interface version (are the CALL directly performed in this case).
 Are interface faster ? (to get the address used by the CALL).

 Thx.
If you actually need speed you would need to use something known as the curiously recurring template, and avoid using virtual (as much as possible) altogether.
May 13 2013