Builtin array and AA efficiency questions

Mike Parker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Oct 15 22:05:17 PDT 2015


On Thursday, 15 October 2015 at 21:48:29 UTC, Random D user wrote:

>> An array uses a block marked for appending, assumeSafeAppend 
>> simply sets how much data is assumed to be valid. Calling 
>> assumeSafeAppend on a block not marked for appending will do 
>> nothing except burn CPU cycles.
>>
>> So yours is not an accurate description.
>
> Related to my question above.
> How do you get a block not marked for appending? a view slice?
>
> Perhaps I should re-read the slice article. I believe it had 
> something like capacity == 0 --> always allocates. Is it this?

There are a handful of attributes that can be set on memory 
allocated by the GC. See the BlkAttr enumeration in core.memory 
[1]. Under the hood, memory for dynamic arrays (slices) is marked 
with BlkAttr.APPENDABLE. If an array pointing to memory not 
marked as such, either manually allocated through the GC, through 
malloc, or another source, then assumeSafeAppend can't help you.

capacity tells you how many more elements can be appended to a 
dynamic array (slice) before an allocation will be triggered. So 
if you get a 0, that means the next append will trigger one. 
Consider this:

int[] dynarray = [1, 2, 3, 4, 5];
auto slice = dynarray[0 .. $-1];

slice points to the same memory as dynarray, but has 4 elements 
whereas dynarray has 5. Appending a single element to slice 
without reallocating will overwrite the 5 in that memory block, 
meaning dynarray will see the new value. For that reason, new 
slices like this will always have a 0 capacity. Append a new item 
to slice and a reallocation occurs, copying the existing elements 
of slice over and adding the new one. This way, dynarray's values 
are untouched and both arrays point to different blocks of memory.

assumeSafeAppend changes this behavior such that appending a new 
item to slice will reuse the same memory block and causing the 5 
to be overwritten. Normally, you don't want to use it unless you 
are sure there are no other slices pointing to the same memory 
block. So it's not something you should be using in a function 
that can receive an array from any source. That array might share 
memory with other slices, the block might not be appendable, you 
have no idea how the slice is actually used... just a bad idea. 
When you have complete control over a slice and know exactly how 
it is used, such as an internal buffer, then it becomes a useful 
tool.

[1] http://dlang.org/phobos/core_memory.html#.GC.BlkAttr


More information about the Digitalmars-d-learn mailing list