Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
December 06, 2016 Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
tl;dr; go to the TLDR section below. :) I use the following command line to identify large symbols. Given a binary named 'deneme', the following command line (at least on Linux) produces the 30 largest symbols in the 'deneme' binary that actually take space in application's memory: nm --print-size --size-sort --radix=d deneme | tail -30 | grep -v " B " A test program: struct S { int i; double d; ubyte[10_000] a; } void main() { } According to the command line above, the largest symbol in that program is S.init: [...] 0000000004446100 0000000000003633 T _D4core4time8Duration13_toStringImplMxFNaNbNfZAya 0000000004504980 0000000000003707 T _d_arraysetlengthiT 0000000004511312 0000000000010016 R _D6deneme1S6__initZ So, the S.init object in that binary is 10016 bytes and that makes sense. Now, request S.init not be generated by initializing the members with void: struct S { int i = void; // (Actually, this =void is not required) double d = void; ubyte[10_000] a = void; } void main() { } Great: Now the large S.init is not a part of the binary: (Well, I think it's still in the BSS section but it does not take space in the memory): [...] 0000000004446100 0000000000003633 T _D4core4time8Duration13_toStringImplMxFNaNbNfZAya 0000000004504980 0000000000003707 T _d_arraysetlengthiT The largest symbol is now something else: _d_arraysetlengthiT. Here comes the trouble... TLDR: Use the void-initialized struct as a class member and that class gets a huge C.init: struct S { int i = void; double d = void; ubyte[10_000] a = void; } class C { S s = void; // (Same result even without the =void) } void main() { } [...] 0000000004446260 0000000000003633 T _D4core4time8Duration13_toStringImplMxFNaNbNfZAya 0000000004505140 0000000000003707 T _d_arraysetlengthiT 0000000006681456 0000000000010032 V _D6deneme1C6__initZ Now we have a 10032 byte C.init. Is there a rationale for this or is this an implementation quality issue? Is there a bug already? I could not find one. Also, I failed to find the "= void" documentation e.g. not on the struct spec page. Thank you, Ali |
December 07, 2016 Re: Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 7 December 2016 at 00:20:11 UTC, Ali Çehreli wrote:
> tl;dr; go to the TLDR section below. :)
>
> I use the following command line to identify large symbols. Given a binary named 'deneme', the following command line (at least on Linux) produces the 30 largest symbols in the 'deneme' binary that actually take space in application's memory:
>
> [...]
I think this is a bug.
Why is the classInit generated at all ?
We don't guarantee blit construction of classes./////////////
|
December 07, 2016 Re: Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 7 December 2016 at 00:20:11 UTC, Ali Çehreli wrote: > Is there a rationale for this or is this an implementation quality issue? Is there a bug already? I could not find one. > > Also, I failed to find the "= void" documentation e.g. not on the struct spec page. https://issues.dlang.org/show_bug.cgi?id=11331 https://issues.dlang.org/show_bug.cgi?id=11817 at least. i.e.: known inefficiency, but nobody feels that it is important enough to get to the top of the list. |
December 07, 2016 Re: Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 7 December 2016 at 00:20:11 UTC, Ali Çehreli wrote: > tl;dr; go to the TLDR section below. :) > > [...] > > struct S { > int i = void; > double d = void; > ubyte[10_000] a = void; > } > > class C { > S s = void; // (Same result even without the =void) > } > > void main() { > } > > [...] > 0000000004446260 0000000000003633 T _D4core4time8Duration13_toStringImplMxFNaNbNfZAya > 0000000004505140 0000000000003707 T _d_arraysetlengthiT > 0000000006681456 0000000000010032 V _D6deneme1C6__initZ > > Now we have a 10032 byte C.init. > > Is there a rationale for this or is this an implementation quality issue? Is there a bug already? I could not find one. > > Also, I failed to find the "= void" documentation e.g. not on the struct spec page. > > Thank you, > Ali Non initialized classes just don't work. Because of the hidden classes fields an initializer is **always** needed. What happens in your example is that the initializer size is sub optimal. A naive make without emplace(): ==== import std.traits, std.c.stdlib; CT make(CT, A...)(A a) { auto memory = malloc(__traits(classInstanceSize, CT)); version(none) emplace!Foo(memory[0..__traits(classInstanceSize, CT)]); static if (__traits(hasMember, CT, "__ctor")) (cast(CT) (memory)).__ctor(a); return cast(CT) memory; } class Foo{void foo(){}} void main() { Foo foo = make!Foo; foo.foo; } ==== crashes with a segfault.... |
December 07, 2016 Re: Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | On 12/06/2016 06:10 PM, Basile B. wrote: > On Wednesday, 7 December 2016 at 00:20:11 UTC, Ali Çehreli wrote: >> tl;dr; go to the TLDR section below. :) >> >> [...] >> >> struct S { >> int i = void; >> double d = void; >> ubyte[10_000] a = void; >> } >> >> class C { >> S s = void; // (Same result even without the =void) >> } >> >> void main() { >> } >> >> [...] >> 0000000004446260 0000000000003633 T >> _D4core4time8Duration13_toStringImplMxFNaNbNfZAya >> 0000000004505140 0000000000003707 T _d_arraysetlengthiT >> 0000000006681456 0000000000010032 V _D6deneme1C6__initZ >> >> Now we have a 10032 byte C.init. >> >> Is there a rationale for this or is this an implementation quality >> issue? Is there a bug already? I could not find one. >> >> Also, I failed to find the "= void" documentation e.g. not on the >> struct spec page. >> >> Thank you, >> Ali > > Non initialized classes just don't work. Because of the hidden classes > fields an initializer is **always** needed. What happens in your example > is that the initializer size is sub optimal. Understood. Please confirm whether the following is a bug. Just because a class uses a *pointer* to a void-initialized struct, the struct gets a .init: struct MyStruct(T) { T[10_000] a = void; } // Same with struct class Outer { MyStruct!ubyte* s; } void main() { } 0000000006681728 0000000000010000 V _D6deneme15__T8MyStructThZ8MyStruct6__initZ Make the struct a non-template and MyStruct.init disappears as expected. Ali |
December 07, 2016 Re: Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 7 December 2016 at 08:46:13 UTC, Ali Çehreli wrote: > On 12/06/2016 06:10 PM, Basile B. wrote: > > On Wednesday, 7 December 2016 at 00:20:11 UTC, Ali Çehreli > wrote: > >> tl;dr; go to the TLDR section below. :) > >> > >> [...] > >> > >> struct S { > >> int i = void; > >> double d = void; > >> ubyte[10_000] a = void; > >> } > >> > >> class C { > >> S s = void; // (Same result even without the =void) > >> } > >> > >> void main() { > >> } > >> > >> [...] > >> 0000000004446260 0000000000003633 T > >> _D4core4time8Duration13_toStringImplMxFNaNbNfZAya > >> 0000000004505140 0000000000003707 T _d_arraysetlengthiT > >> 0000000006681456 0000000000010032 V _D6deneme1C6__initZ > >> > >> Now we have a 10032 byte C.init. > >> > >> Is there a rationale for this or is this an implementation > quality > >> issue? Is there a bug already? I could not find one. > >> > >> Also, I failed to find the "= void" documentation e.g. not > on the > >> struct spec page. > >> > >> Thank you, > >> Ali > > > > Non initialized classes just don't work. Because of the > hidden classes > > fields an initializer is **always** needed. What happens in > your example > > is that the initializer size is sub optimal. I've said bullshit here. In case of manual init, gaps couldn't be handled easily anyway. We have the aggregate size, we have a pointer to its initializer, that's all. > > Understood. Please confirm whether the following is a bug. Just because a class uses a *pointer* to a void-initialized struct, the struct gets a .init: > > struct MyStruct(T) { > T[10_000] a = void; > } > > // Same with struct > class Outer { > MyStruct!ubyte* s; > } > > void main() { > } > > 0000000006681728 0000000000010000 V _D6deneme15__T8MyStructThZ8MyStruct6__initZ > > Make the struct a non-template and MyStruct.init disappears as expected. > > Ali I wouldn't say it's a bug rather an enhancement request. Unfortunately with my expertise level I can't say more. I think that one of the GDC member expressed some interest into making initialization of aggregates better. It was when A.Alexandrescu worked on RCString, I can't find the link anymore, it was about RCString init being slow, in comparison to a cpp equivalent. It looks like this discussion is highly related. |
December 07, 2016 Re: Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | On 12/07/2016 02:56 AM, Basile B. wrote: > rather an enhancement request https://issues.dlang.org/show_bug.cgi?id=16956 Thank you, Ali |
December 07, 2016 Re: Large .init for class containing void-initialized struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to ketmar | On Wednesday, 7 December 2016 at 00:35:21 UTC, ketmar wrote: > On Wednesday, 7 December 2016 at 00:20:11 UTC, Ali Çehreli wrote: >> Is there a rationale for this or is this an implementation quality issue? Is there a bug already? I could not find one. >> >> Also, I failed to find the "= void" documentation e.g. not on the struct spec page. > > https://issues.dlang.org/show_bug.cgi?id=11331 > https://issues.dlang.org/show_bug.cgi?id=11817 > > at least. Yep, many bugs about it. > i.e.: known inefficiency, but nobody feels that it is important enough to get to the top of the list. I think what's blocking things is: ``` T a; T b; assert(a == b); ``` Someone noted that that's a language guarantee, which would have to be relaxed for aggregates with `= void`initialized fields. -Johan |
Copyright © 1999-2021 by the D Language Foundation