Jump to page: 1 2
Thread overview
Size of type bug in D?
Apr 09, 2004
Walter
No Size of type bug in D!
Apr 10, 2004
Walter
Apr 15, 2004
Walter
Efficient interfaces (was Re: No Size of type bug in D!)
Apr 16, 2004
Ben Hinkle
Apr 16, 2004
Ilya Minkov
Interface code snippet:
Re: Interface code snippet: (Improved version)
Apr 18, 2004
Walter
Apr 25, 2004
Walter
April 09, 2004
I can't get the real size of a class:

  class FuBar {
    int m1, m2;
    float m3;
  }

  int main() {
    FuBar x = new FuBar;
    printf("sizeof FuBar = %d\n", FuBar.size);
    printf("sizeof FuBar = %d\n", FuBar.sizeof);
    printf("sizeof FuBar = %d\n", x.size);
    printf("sizeof FuBar = %d\n", x.sizeof);
    return 0;
  }

All of these calls output 4 bytes.

-- 
Christopher Diggins
http://www.cdiggins.com
http://www.heron-language.com


April 09, 2004
"christopher diggins" <cdiggins@users.sourceforge.net> wrote in message news:c56iq9$2pmp$1@digitaldaemon.com...
> I can't get the real size of a class:
>
>   class FuBar {
>     int m1, m2;
>     float m3;
>   }
>
>   int main() {
>     FuBar x = new FuBar;
>     printf("sizeof FuBar = %d\n", FuBar.size);
>     printf("sizeof FuBar = %d\n", FuBar.sizeof);
>     printf("sizeof FuBar = %d\n", x.size);
>     printf("sizeof FuBar = %d\n", x.sizeof);
>     return 0;
>   }
>
> All of these calls output 4 bytes.

Right. That's because you're getting the size of a reference to a class
object. To get the size of the object itself:
    x.classinfo.init.length


April 10, 2004
"Walter" <walter@digitalmars.com> wrote in message news:c56p1b$2lj$2@digitaldaemon.com...
>
> "christopher diggins" <cdiggins@users.sourceforge.net> wrote in message news:c56iq9$2pmp$1@digitaldaemon.com...
> > I can't get the real size of a class:
<snip>
>
> Right. That's because you're getting the size of a reference to a class
> object. To get the size of the object itself:
>     x.classinfo.init.length

Thank you for that Walter. So armed with that new knowledge here is a very short example program:

  interface IFu {
    void Fu();
  }

  interface IBar {
    void Bar();
  }

  class Fu : IFu {
    void Fu() { printf("fubar fu\n"); };
  }

  class FuBar : IFu, IBar {
    void Fu() { printf("fubar fu\n"); };
    void Bar() { printf("fubar bar\n"); };
  }

  class Empty {
  }

  int main() {
    Empty x = new Empty;
    Fu y = new Fu;
    FuBar z = new FuBar;
    printf("sizeof Empty = %d\n", x.classinfo.init.length); // outputs 8
    printf("sizeof Fu = %d\n", y.classinfo.init.length); // outputs 12
    printf("sizeof Fubar = %d\n", z.classinfo.init.length); // outputs 16
    return 0;
  }

This supports what I had suspected, that there are extra vtable pointers introduced for each interface. If you used fat pointers (double width) for interface references you could avoid the extra space overhead. There are also potentially significant performance advantages of not using vtables to implement interfaces. Is this something which is interesting to you? Or should I let this sleeping dog lie?

-- 
Christopher Diggins
http://www.cdiggins.com
http://www.heron-language.com


April 10, 2004
"christopher diggins" <cdiggins@users.sourceforge.net> wrote in message news:c57q4g$1nep$1@digitaldaemon.com...
> This supports what I had suspected, that there are extra vtable pointers introduced for each interface.

That's correct.

> If you used fat pointers (double width) for
> interface references you could avoid the extra space overhead.
> There are
> also potentially significant performance advantages of not using vtables
to
> implement interfaces.

I don't see how.

> Is this something which is interesting to you? Or
> should I let this sleeping dog lie?

I'm curious <g>.


April 11, 2004
"Walter" <walter@digitalmars.com> wrote in message news:c59cop$143a$1@digitaldaemon.com...
>
> "christopher diggins" <cdiggins@users.sourceforge.net> wrote in message news:c57q4g$1nep$1@digitaldaemon.com...
> > This supports what I had suspected, that there are extra vtable pointers introduced for each interface.
>
> That's correct.
>
> > If you used fat pointers (double width) for
> > interface references you could avoid the extra space overhead.
> > There are
> > also potentially significant performance advantages of not using vtables
> to
> > implement interfaces.
>
> I don't see how.
>
> > Is this something which is interesting to you? Or
> > should I let this sleeping dog lie?
>
> I'm curious <g>.

Then now that I have piqued your interest, the technique is to use a double width pointer when referring to an object by reference. One part points to the object while the other points to a function table representing the functions of the interface. I wrote a C++ language extension to demonstrate the technique and have made it freely available at http://www.heron-language.com/heronfront.html .

Let me know if you have any questions.

Christopher Diggins
http://www.cdiggins.com
http://www.heron-language.com


April 15, 2004
I just don't see where the performance difference is coming from. Correct me if I'm wrong, but Heron moves the vptr from the class object to the class reference. How does that make it faster?

Consider also that in D, a reference to an interface is really just a pointer to a vptr.


April 15, 2004
When using the object directly (referring to it by its concrete type) the vtable is not needed because the functions aren't virtual. Also when referring to an object by the interface once the first call to the object is dispatched using a virtual table, calls within that function to other members of the interface shouldn't be dispatched using the vtable. Doing so would be inefficient and wrong. Am I making sense?

Btw: I am working on a significantly simplified version of HeronFront that integrates smoother with standard C++ and requires less use of a pre-processor. I will announce it on this newsgroup when it is available.

-- 
Christopher Diggins
http://www.cdiggins.com
http://www.heron-language.com


"Walter" <walter@digitalmars.com> wrote in message news:c5mhta$12t$1@digitaldaemon.com...
> I just don't see where the performance difference is coming from. Correct
me
> if I'm wrong, but Heron moves the vptr from the class object to the class reference. How does that make it faster?
>
> Consider also that in D, a reference to an interface is really just a pointer to a vptr.
>
>


April 16, 2004
[snip]
>Also when
>referring to an object by the interface once the first call to the object is
>dispatched using a virtual table, calls within that function to other
>members of the interface shouldn't be dispatched using the vtable.
[snip]

Hmm. Does Heron allow a subclass to call a superclass implementation? If so then how are the function calls in the superclass made? If they are direct then they would not dispatch to the subclass methods, which seems like a bug. The only way out of this problem that I can see is that each method has two implementations: one with vtable dispatching to be used when called by the syntax super.foo() and another with direct function calls to be used elsewhere. Methods that aren't overridden get the dispatching version.

Am I understanding this correctly? It seems like any C++ or D compiler could make such a time/space tradeoff during code generation - much like inlining functions is a time/space tradeoff.

April 16, 2004
"Ben Hinkle" <bhinkle4@juno.com> wrote in message news:beiu7052nddt3gomhqbno7coqnphk7trma@4ax.com...
>
> [snip]
> >Also when
> >referring to an object by the interface once the first call to the object
is
> >dispatched using a virtual table, calls within that function to other members of the interface shouldn't be dispatched using the vtable.
> [snip]
>
> Hmm. Does Heron allow a subclass to call a superclass implementation?

I wasn't discussing Heron. Heron doesn't allow class inheritance.

> If so then how are the function calls in the superclass made? If they are direct then they would not dispatch to the subclass methods, which seems like a bug. The only way out of this problem that I can see is that each method has two implementations: one with vtable dispatching to be used when called by the syntax super.foo() and another with direct function calls to be used elsewhere. Methods that aren't overridden get the dispatching version.
>
> Am I understanding this correctly? It seems like any C++ or D compiler could make such a time/space tradeoff during code generation - much like inlining functions is a time/space tradeoff.

I think you got off track somewhere. The issue is that interfaces implemented as ABC's are inherently less efficient (because of the wrognful and unnecessary virtualization of functions) than when implemented alternatively such as demonstrated by the HeronFront project at http://www.heron-language.com/heronfront.html .

-- 
Christopher Diggins
http://www.cdiggins.com
http://www.heron-language.com


April 16, 2004
Hi Walter,

Here is a sample implementation of a struct FuBar implementing an interface InterfaceFuBar which contains two functions: void Fu() and void Bar(), I'll let you do your own poking and prodding at the example and I welcome any feedback on the code itself as I am somewhat rusty at C++. Let me know if you require commenting of the code etc.

#include <iostream>
template<typename SELF> struct ITABLE_InterfaceFuBar {
  void(SELF::*Fu)();
  void(SELF::*Bar)();
};
struct InterfaceFuBar {
  struct DUMMY_InterfaceFuBar {
    void Fu() { };
    void Bar() { };
  };
  struct DUMMY_ITABLE_InterfaceFuBar : public
ITABLE_InterfaceFuBar<DUMMY_InterfaceFuBar>  {  };
  DUMMY_InterfaceFuBar* mpObject;
  DUMMY_ITABLE_InterfaceFuBar* mpTable;
  InterfaceFuBar(void* pObject = NULL, void* pTable = NULL) {
    mpObject = (DUMMY_InterfaceFuBar*)pObject;
    mpTable = (DUMMY_ITABLE_InterfaceFuBar*)pTable;
  };
  void Fu() { (mpObject->*(mpTable->Fu))(); };
  void Bar() { (mpObject->*(mpTable->Bar))(); };
};
template<typename I, typename M> struct Implementor {
  operator I() { return I(NULL, NULL); };
};
template<typename M> struct Implementor<InterfaceFuBar, M> {
  operator InterfaceFuBar() {
    static ITABLE_InterfaceFuBar<M> tmp = { M::Fu, M::Bar };
    return InterfaceFuBar(this, (void*)&tmp);
  };
};
struct FuBar : public Implementor<InterfaceFuBar, FuBar> {
  void Fu() { std::cout << "fu" << std::endl; };
  void Bar() { std::cout << "bar" << std::endl; };
};
int main() {
  FuBar f;
  InterfaceFuBar i = f;
  i.Fu();
  std::cin.get();
  return 0;
}

-- 
Christopher Diggins
http://www.cdiggins.com
http://www.heron-language.com



« First   ‹ Prev
1 2