Allocate N elements

monarch_dodra monarchdodra at gmail.com
Tue Jul 16 01:58:21 PDT 2013


On Monday, 15 July 2013 at 17:39:43 UTC, H. S. Teoh wrote:
> On Mon, Jul 15, 2013 at 07:32:37PM +0200, monarch_dodra wrote:
>> On Monday, 15 July 2013 at 15:54:57 UTC, bearophile wrote:
>> >monarch_dodra:
>> >
>> >>>But that (of new arrays) is a bad design, it wastes too much
>> >>>memory, and I think it should be fixed. In Python this 
>> >>>doesn't
>> >>>overallocate:
>> >>
>> >>So what? The only thing you showed, is that 
>> >>minimallyInitialized
>> >>doesn't know how much it allocated. If you allocate 513 
>> >>elements
>> >>with malloc, you'll way over allocate too. What's your point?
>> >>You'll waste memory either way.
>> >
>> >I didn't know it, sorry. I forgot.
>> >Can we let minimallyInitializedArray know the capacity?
>> 
>> I'm working on it ;)
>> 
>> >Regarding the small arrays, so to avoid the memory wasting you
>> >need to allocate a larger one and slice it.
>> >
>> >Bye,
>> >bearophile
>> 
>> One of the problems is that when you want an arbitrarily sized
>> allocation, it is usually standard to allocate 2^N in size. 
>> While
>> this is optimal for "traditional" malloc, it's actually the 
>> *worst*
>> allocation size you could ask for a GC array with appendable 
>> info
>> (eg, traditional new) :/
>
> This is wrong. The 2^N size should be applied *after* GC 
> appendable info
> (or whatever else bookkeeping info you need) has been accounted 
> for, not
> before. If the GC header/whatever requires, say, 16 bytes, then 
> the
> ideal array size should be 2^N-16, so that everything fits 
> neatly within
> a power of 2. Otherwise you end up with 2^N+16 bytes that are 
> actually
> allocated, and it just goes downhill from there.
>
>
> T

Just to be clear, the GC itself has no overhead. Only the 
APPENDABLE bookkeeping does any overhead.
EG: GC.malloc(1024);
This will allocate a 1024 byte block. No problem here.

HOWEVER, if you write:
int[] arr = new int[](1000); //Allocates a  4Ki block
int[] arr = new int[](1024); //Allocates an 8Ki block
The example is a bit extreme, but you should get what I mean.

If you do a malloc with GC.BlkAttr.APPENDABLE, you will also get 
exactly what you asked for. However, it will be the user's 
responsibility to take into account that some of those allocated 
bytes will not actually be useable (the APPENDABLE block).

FYI, the way APPEDNABLE works:
Arrays 1-255 bytes: 1 extra byte will be appended for used 
capacity info at the end of the array.
Arrays 256-2046: 2 extra bytes will be appended.
2047+: The array will *start* with a 16 byte block for appendable 
info. A dummy 1 byte block will also be appended to the end of 
the block, for "arr[$ .. $]". (So yes, you need to accound for a 
*17* byte overhead)

That said, allocating an array using a straight up 
malloc(APPEDNABLE) is *very* complicated, and it is all very 
specific to the current GC anyways: It is very very error prone, 
and non portable.


More information about the Digitalmars-d-learn mailing list