www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - StructType.init and StructType() cause a allocation

reply Benjamin Thaut <code benjamin-thaut.de> writes:
If T is a struct both of the following statements will lead to a call of 
the _d_arrayliteral function which will allocate a array of the size of 
the struct just to initialize it!!

void T[] data = ...;

data[0] = T.init;
data[0] = T();

This has proven to be the biggest performance bottleneck in my current 
codebase, replacing this statement with a unneccessary workaround speeds 
my code up by factor 100. This is the cause because all of my container 
classes tend to reinitialize the contents of the data arrays they are 
holding. Also this bug makes it very hard to write non leaking code when 
not using a GC. The replacement code could be

T temp;
data[0] = temp;

Which works correctly as long as T is publicly accessible, if it is a 
private type this will not compile. Then you have to do some more fancy 
stuff like:

void[T.sizeof] temp;
void[] initMem = typeid(T).init();
if(initMem.ptr is null)
   memset(temp.ptr, 0, temp.length);
else
   temp[] = initMem[];
data[0] = *cast(T*)temp.ptr;

How hard would it be to fix this?

It is really a shame that reinitalizing a struct
a) is a major performance bottleneck
b) leaks memory

I created a bug ticket for this 6 months ago, but it has been ignored so 
far: http://d.puremagic.com/issues/show_bug.cgi?id=7271

Kind Regards
Benjamin Thaut
Jun 30 2012
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Benjamin Thaut:

 I created a bug ticket for this 6 months ago, but it has been 
 ignored so far: 
 http://d.puremagic.com/issues/show_bug.cgi?id=7271

A similar bug was fixed very recently. D used to allocate a dynamic array of length 1 when you write "new T" where T is a struct. I don't know if that bug fix (in dmd 2.060alpha) has fixed your problem too. Such kind of bugs do get fixed, eventually :-) Bye, bearophile
Jun 30 2012
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 30.06.2012 13:52, schrieb bearophile:
 I don't know if that bug fix (in dmd 2.060alpha) has fixed your
 problem too.

I have compiled this code from your issue 7271 with the latest beta: struct MemoryBlockInfo { size_t size; long[10] backtrace; int backtraceSize; this(size_t size) { this.size = size; } } void main() { MemoryBlockInfo info; info = MemoryBlockInfo.init; //array allocation here } Compiling it with no optimization it gives: _D4temp15MemoryBlockInfo6__ctorMFkZS4temp15MemoryBlockInfo enter 4,0 mov ECX,8[EBP] mov [EAX],ECX leave ret 4 __Dmain comdat enter 060h,0 push ESI push EDI mov ECX,018h xor EAX,EAX lea EDI,-060h[EBP] rep stosd mov ESI,offset FLAT:_D4temp15MemoryBlockInfo6__initZ lea EDI,-060h[EBP] mov CL,018h rep movsd pop EDI pop ESI leave ret With -O -release -inline it becomes: _D4temp15MemoryBlockInfo6__ctorMFkZS4temp15MemoryBlockInfo comdat push EAX mov ECX,8[ESP] mov [EAX],ECX pop ECX ret 4 __Dmain comdat sub ESP,064h mov ECX,018h xor EAX,EAX push EDI lea EDI,4[ESP] rep stosd pop EDI add ESP,064h ret In both cases I don't see a memory allocation. Bye, bearophile

Thank you, Its very nice to know that this got fixed. Someone might want to close the ticket as duplicate then. Kind Regards Benjamin Thaut
Jun 30 2012
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 I don't know if that bug fix (in dmd 2.060alpha) has fixed your 
 problem too.

I have compiled this code from your issue 7271 with the latest beta: struct MemoryBlockInfo { size_t size; long[10] backtrace; int backtraceSize; this(size_t size) { this.size = size; } } void main() { MemoryBlockInfo info; info = MemoryBlockInfo.init; //array allocation here } Compiling it with no optimization it gives: _D4temp15MemoryBlockInfo6__ctorMFkZS4temp15MemoryBlockInfo enter 4,0 mov ECX,8[EBP] mov [EAX],ECX leave ret 4 __Dmain comdat enter 060h,0 push ESI push EDI mov ECX,018h xor EAX,EAX lea EDI,-060h[EBP] rep stosd mov ESI,offset FLAT:_D4temp15MemoryBlockInfo6__initZ lea EDI,-060h[EBP] mov CL,018h rep movsd pop EDI pop ESI leave ret With -O -release -inline it becomes: _D4temp15MemoryBlockInfo6__ctorMFkZS4temp15MemoryBlockInfo comdat push EAX mov ECX,8[ESP] mov [EAX],ECX pop ECX ret 4 __Dmain comdat sub ESP,064h mov ECX,018h xor EAX,EAX push EDI lea EDI,4[ESP] rep stosd pop EDI add ESP,064h ret In both cases I don't see a memory allocation. Bye, bearophile
Jun 30 2012