www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Structs insted of classes for Performance

reply "Frustrated" <Who where.com> writes:
I know the difference between a struct and a class but I remember 
seeing somewhere that structs are much faster than classes in D 
for some strange reason.

I'm not worried too much about class allocation performance 
because I will try and use classes when they will not be created 
frequently and structs or class reuse when they will be.

So, is the only argument really about performance when creating 
structs vs creating classes or was there some finer detail I 
missed?

Basically that boils down to stack allocation vs heap allocation 
speed? Which, while allocation on the heap shouldn't be too much 
slower than stack, the GC makes it worse?
Apr 20 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
My understanding is not perfect. There may be compiler and CPU 
optimizations that I am not aware of.

On 04/20/2014 08:03 AM, Frustrated wrote:

 is the only argument really about performance when creating
 structs vs creating classes
Not only creating but also when using. A class variable is a reference to the actual object, implemented by the compiler as a pointer. So, there is that extra indirection overhead to access member variables of a class object. When the class variable and the object are far apart in memory, they may be fall outside of CPU caches. Further, unless they are defined as final or static, class member functions are virtual. Virtual member funtions are dispatched through the virtual function table (vtbl) pointer. So, a call like o.foo() must first hit the class vtbl in memory, read the value of the function pointer off that table and then jump to the function. Related to the above, class objects are larger than struct objects because they have the extra vtbl pointer, as well as another pointer (monitor) that allows every class object to be used as a synchronization item in concurrency. Larger objects are more expensive because less of those can fit in CPU caches.
 Basically that boils down to stack allocation vs heap allocation speed?
Not to forget, struct objects can be allocated on the stack as well by std.typecons.scoped.
 Which, while allocation on the heap shouldn't be too much slower than
 stack, the GC makes it worse?
Stack allocation almost does not exist as some location on the stack is reserved for a given object. There is no allocation or deallocation cost at runtime other than certain decisions made by the compiler at compile time. On the other hand, any dynamic allocation and deallocation scheme must do some work to find room for the object at runtime. Ali
Apr 20 2014
parent reply "Frustrated" <Who where.com> writes:
On Sunday, 20 April 2014 at 16:56:59 UTC, Ali Çehreli wrote:
 My understanding is not perfect. There may be compiler and CPU 
 optimizations that I am not aware of.

 On 04/20/2014 08:03 AM, Frustrated wrote:

 is the only argument really about performance when creating
 structs vs creating classes
Not only creating but also when using. A class variable is a reference to the actual object, implemented by the compiler as a pointer. So, there is that extra indirection overhead to access member variables of a class object. When the class variable and the object are far apart in memory, they may be fall outside of CPU caches. Further, unless they are defined as final or static, class member functions are virtual. Virtual member funtions are dispatched through the virtual function table (vtbl) pointer. So, a call like o.foo() must first hit the class vtbl in memory, read the value of the function pointer off that table and then jump to the function. Related to the above, class objects are larger than struct objects because they have the extra vtbl pointer, as well as another pointer (monitor) that allows every class object to be used as a synchronization item in concurrency. Larger objects are more expensive because less of those can fit in CPU caches.
Yes, but this is the standard argument between structs and classes. Obviously the additional benefits of classes cost... else no one would use structs. If structs had inheritance, there would be no real reason for classes. I don't mind the cost of classes because I will try and use them were appropriately. Also, these problems are not language specific but simply because classes are heavier. The article I read was about D's specific issues and that using structs GREATLY sped up certain things... I'm sure it had to do with the GC and all that but can't remember.
 Basically that boils down to stack allocation vs heap
allocation speed? Not to forget, struct objects can be allocated on the stack as well by std.typecons.scoped.
 Which, while allocation on the heap shouldn't be too much
slower than
 stack, the GC makes it worse?
Stack allocation almost does not exist as some location on the stack is reserved for a given object. There is no allocation or deallocation cost at runtime other than certain decisions made by the compiler at compile time. On the other hand, any dynamic allocation and deallocation scheme must do some work to find room for the object at runtime. Ali
Again, all those arguments are about the specific difference between a struct and class and apply to all languages that use those types of structures. In D though, I guess because of the GC(but which is why I am asking because I don't know specifically), classes could be much slower due to all the references causing the GC to take longer scan the heap and all that. If allocate or free a lot of classes in a short period of time it also can cause issues IIRC. I just can't remember if there was some other weird reasons why D's classes are, in general, not as performant as they should be. If I remember correctly, I came across a page that compared a few test cases with the GC on and off and there was a huge factor involved showing that the GC had a huge impact on performance.
Apr 20 2014
parent "anonymous" <anonymous example.com> writes:
On Sunday, 20 April 2014 at 18:08:19 UTC, Frustrated wrote:
 In D though, I guess because of the GC(but which is why I am 
 asking because I don't know specifically), classes could be 
 much slower due to all the references causing the GC to take 
 longer scan the heap and all that. If allocate or free a lot of 
 classes in a short period of time it also can cause issues IIRC.
(You probably now this, but just so that we're on the same page:) Structs on the stack are not GC'ed. They don't add garbage, they don't trigger collections. When you `new` a struct the GC is in charge again. Class instances on the heap are GC'ed. Putting them on the stack isn't typical, and somewhat for experts. After all, if you want to put it on the stack, you can probably use a (more light-weight) struct instead. I'd expect many short-lived objects to not perform very well. There would be much garbage, it would have to be collected often. D's GC isn't the best in town. Advice regarding GC performance often comes down to "avoid collections".
 I just can't remember if there was some other weird reasons why 
 D's classes are, in general, not as performant as they should 
 be. If I remember correctly, I came across a page that compared 
 a few test cases with the GC on and off and there was a huge 
 factor involved showing that the GC had a huge impact on 
 performance.
I guess that shows that it's the collections that are slow. So, D's classes probably /could/ perform better with a better GC. That's mostly an issue with the GC implementation, I think, not so much a consequence from D's design. Coming back to your original questions: On Sunday, 20 April 2014 at 15:03:34 UTC, Frustrated wrote:
 So, is the only argument really about performance when creating 
 structs vs creating classes or was there some finer detail I 
 missed?
Yes, it's all about performance, I think. You can write correct programs using classes for everything.
 Basically that boils down to stack allocation vs heap 
 allocation speed? Which, while allocation on the heap shouldn't 
 be too much slower than stack, the GC makes it worse?
Stack vs heap does make a difference. It's an indirection and smarter people than me can think about caches and stuff. The GC does make it worse, especially in its current incarnation. But then, if you care enough about performance, and you need to use the heap, then D does allow you to manage your memory yourself, without going through the GC.
Apr 20 2014