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