www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Class instance memory overhead lower than 3 words?

reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
Why is the memory overhead for a class instance as high as 3 
words (24 bytes on 64-bit systems? I find that annoyingly much 
for my knowledge database application. I'm aware of extern(C++), 
having one word overhead, but such extern(C++)-classes cannot use 
all of D; I get compilation errors such as

node.d(99,25): Error: Internal Compiler Error: type 
`inout(Edge)[]` can not be mapped to C++
Jan 24
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Jan 24, 2018 at 09:48:21PM +0000, NordlŲw via Digitalmars-d-learn wrote:
 Why is the memory overhead for a class instance as high as 3 words (24
 bytes on 64-bit systems? I find that annoyingly much for my knowledge
 database application.
[...] There's been an attempt to get rid of the Monitor field, which takes up one word, but it didn't seem to have gone anywhere the last time it was discussed. I believe originally it was always initialized, but lately it seems to have been changed to be lazily initialized, so at least you'll only incur the computational cost if you actually use it. Nevertheless, the field itself is still there. T -- What is Matter, what is Mind? Never Mind, it doesn't Matter.
Jan 24
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 24 January 2018 at 21:47:26 UTC, H. S. Teoh wrote:
 On Wed, Jan 24, 2018 at 09:48:21PM +0000, Nordlöw via 
 Digitalmars-d-learn wrote:
 Why is the memory overhead for a class instance as high as 3 
 words (24 bytes on 64-bit systems? I find that annoyingly much 
 for my knowledge database application.
[...] There's been an attempt to get rid of the Monitor field, which takes up one word, but it didn't seem to have gone anywhere the last time it was discussed. I believe originally it was always initialized, but lately it seems to have been changed to be lazily initialized, so at least you'll only incur the computational cost if you actually use it. Nevertheless, the field itself is still there. T
Can I use `*(cast(size_t*)&c.__monitor)` for storing my own stuff in a class instance `c` if I never use monitors? :) BTW: the documentation on the concept of monitors is kind of sparse here https://dlang.org/spec/class.html#class_properties What is the `__monitor` property used for? Something with synchronized member functions?
Jan 24
parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 24 January 2018 at 22:27:40 UTC, Nordlöw wrote:
 On Wednesday, 24 January 2018 at 21:47:26 UTC, H. S. Teoh wrote:
 On Wed, Jan 24, 2018 at 09:48:21PM +0000, Nordlöw via 
 Digitalmars-d-learn wrote:
 Why is the memory overhead for a class instance as high as 3 
 words (24 bytes on 64-bit systems? I find that annoyingly 
 much for my knowledge database application.
[...] There's been an attempt to get rid of the Monitor field, which takes up one word, but it didn't seem to have gone anywhere the last time it was discussed. I believe originally it was always initialized, but lately it seems to have been changed to be lazily initialized, so at least you'll only incur the computational cost if you actually use it. Nevertheless, the field itself is still there. T
Can I use `*(cast(size_t*)&c.__monitor)` for storing my own stuff in a class instance `c` if I never use monitors? :)
Maybe, the runtime when destroying that class might think the monitor is set and try and destroy the mutex it thinks is where the pointer points to.
 BTW: the documentation on the concept of monitors is kind of 
 sparse here

 https://dlang.org/spec/class.html#class_properties

 What is the `__monitor` property used for? Something with 
 synchronized member functions?
It is used for ``` MyClass mc; synchronized(mc) // <- { ... } ``` and I believe synchronized member functions and member functions of `synchronized class` (which are the same thing really). The __monitor field points to a mutex object which is managed by the runtime.
Jan 24
prev sibling next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 24 January 2018 at 21:48:21 UTC, Nordlöw wrote:
 Why is the memory overhead for a class instance as high as 3 
 words (24 bytes on 64-bit systems? I find that annoyingly much 
 for my knowledge database application. I'm aware of 
 extern(C++), having one word overhead, but such 
 extern(C++)-classes cannot use all of D; I get compilation 
 errors such as

 node.d(99,25): Error: Internal Compiler Error: type 
 `inout(Edge)[]` can not be mapped to C++
One pointer for the vtbl, one for the monitor, not sure what the other one is. C++ classes have one pointer for the vtbl at offset of -1 size_t.sizeof Declaring that particular method as extern(D) will fix that problem.
Jan 24
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, January 25, 2018 00:10:32 Nicholas Wilson via Digitalmars-d-
learn wrote:
 One pointer for the vtbl, one for the monitor, not sure what the
 other one is.
The TypeInfo maybe? I'm not sure where that lives. - Jonathan M Davis
Jan 24
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/24/2018 05:43 PM, Jonathan M Davis wrote:
 On Thursday, January 25, 2018 00:10:32 Nicholas Wilson via Digitalmars-d-
 learn wrote:
 One pointer for the vtbl, one for the monitor, not sure what the
 other one is.
The TypeInfo maybe? I'm not sure where that lives. - Jonathan M Davis
Nested classes have that third pointer: class A { } static assert(__traits(classInstanceSize, A) == 2 * (void*).sizeof); void main() { class B { } static assert(__traits(classInstanceSize, B) == 3 * (void*).sizeof); } Are there other cases? Ali
Jan 24
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, January 24, 2018 17:50:35 Ali «ehreli via Digitalmars-d-learn 
wrote:
 On 01/24/2018 05:43 PM, Jonathan M Davis wrote:
 On Thursday, January 25, 2018 00:10:32 Nicholas Wilson via
 Digitalmars-d-

 learn wrote:
 One pointer for the vtbl, one for the monitor, not sure what the
 other one is.
The TypeInfo maybe? I'm not sure where that lives. - Jonathan M Davis
Nested classes have that third pointer: class A { } static assert(__traits(classInstanceSize, A) == 2 * (void*).sizeof); void main() { class B { } static assert(__traits(classInstanceSize, B) == 3 * (void*).sizeof); } Are there other cases?
Well, a class nested inside another class would, but that's just another type of nested class. If it's not nested, it won't have a pointer to any kind of outer scope though. - Jonathan M Davis
Jan 24
prev sibling next sibling parent kinke <noone nowhere.com> writes:
On Wednesday, 24 January 2018 at 21:48:21 UTC, Nordlöw wrote:
 Why is the memory overhead for a class instance as high as 3 
 words (24 bytes on 64-bit systems? I find that annoyingly much 
 for my knowledge database application. I'm aware of 
 extern(C++), having one word overhead, but such 
 extern(C++)-classes cannot use all of D; I get compilation 
 errors such as

 node.d(99,25): Error: Internal Compiler Error: type 
 `inout(Edge)[]` can not be mapped to C++
If you don't need C++ interop and only care about getting rid of the monitor pointer, you can declare the class as C++ class but use the D linkage/ABI for all functions, so that they accept D slices: extern(C++) class Node { extern(D): void foo(Node[] nodes) {} } Is a struct not an option?
Jan 25
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/24/18 4:48 PM, Nordlöw wrote:
 Why is the memory overhead for a class instance as high as 3 words (24 
 bytes on 64-bit systems? I find that annoyingly much for my knowledge 
 database application. I'm aware of extern(C++), having one word 
 overhead, but such extern(C++)-classes cannot use all of D; I get 
 compilation errors such as
 
 node.d(99,25): Error: Internal Compiler Error: type `inout(Edge)[]` can 
 not be mapped to C++
Should be 2 words, the monitor and the typeinfo pointer. What is the 3rd one? On 64-bit macos: class C { } void main() { import std.stdio; writeln(typeid(C).initializer.length); // 16 } -Steve
Jan 26