copy and array length vs capacity. (Doc suggestion?)

Jon D via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Nov 23 20:14:33 PST 2015


On Tuesday, 24 November 2015 at 01:00:40 UTC, Steven 
Schveighoffer wrote:
> On 11/23/15 7:29 PM, Ali Çehreli wrote:
>> On 11/23/2015 04:03 PM, Steven Schveighoffer wrote:
>>  > On 11/23/15 4:29 PM, Jon D wrote:
>>
>>  >> In the example I gave, what I was really wondering was if 
>> there is a
>>  >> difference between allocating with 'new' or with 
>> 'reserve', or with
>>  >> 'length', for that matter. That is, is there a material 
>> difference
>>  >> between:
>>  >>
>>  >>      auto x = new int[](n);
>>  >>      int[] y; y.length = n;
>>  >
>>  > There is no difference at all, other than the function that 
>> is called
>>  > (the former will call an allocation function, the latter 
>> will call a
>>  > length setting function, which then will determine if more 
>> data is
>>  > needed, and finding it is, call the allocation function).
>>
>> Although Jon's example above does not compare reserve, I have 
>> to ask:
>> How about non-trivial types? Both cases above would set all 
>> elements to
>> ..init, right? So, I think reserve would be faster if copy() 
>> knew how to
>> take advantage of capacity. It could emplace elements instead 
>> of
>> copying, no?
>
> I think the cost of looking up the array metadata is more than 
> the initialization of elements to .init. However, using an 
> Appender would likely fix all these problems.
>
> You could also use 
> https://dlang.org/phobos/std_array.html#uninitializedArray to 
> create the array before copying. There are quite a few options, 
> actually :)
>
> A delegate is also surprisingly considered an output range! 
> Because why not? So you can do this too as a crude substitute 
> for appender (or for testing performance):
>
> import std.range; // for iota
> import std.algorithm;
>
> void main()
> {
>    int[] arr;
>    arr.reserve(100);
>
>    iota(100).copy((int a) { arr ~= a;});
> }
>
> -Steve

Thanks. I was also wondering if that initial allocation could be 
avoided. Code I was writing involved repeatedly using a buffer in 
a loop. I was trying out taskPool.amap, which needs a random 
access range. This meant copying from the input range being read. 
Something like:

     auto input = anInfiniteRange();
     auto bufsize = workPerThread * taskPool.size();
     auto workbuf = new int[](bufsize);
     auto results = new int[](bufsize);
     while (true) {
         input.take(bufsize).copy(workbuf);
         input.popFront(bufsize);
         taskPool.amap!expensiveCalc(workbuf, workPerThread, 
results);
         results.doSomething();
     }

I'm just writing a toy example, but it is where these questions 
came from. For this example, the next step would be to allow the 
buffer size to change while iterating.

--Jon


More information about the Digitalmars-d-learn mailing list