Thread overview
Interface vs pure abstract class - speed.
May 12, 2013
Diggory
May 12, 2013
Maxim Fomin
May 12, 2013
Maxim Fomin
May 12, 2013
D-Ratiseur
May 13, 2013
Sean Cavanaugh
May 12, 2013
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
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
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
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
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
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
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 13, 2013
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.