Thread overview
Reserve on dynamic arrays
Jul 14, 2016
cym13
Jul 14, 2016
Jonathan M Davis
Jul 14, 2016
cym13
July 14, 2016
Does changing the capacity of dynamic arrays actually do anything with respect to memory allocation? I have the following data with DMD 2.071.1

// With dmd -profile=gc

void main() {
    import std.stdio;

    int[] arr = [1, 1, 1];
    arr.reserve(512);

    foreach (i ; 0..10)
        arr ~= 42;
}

/*
 * bytes allocated, allocations, type, function, file:line
 *              40              10 int[] D main test.d:8
 *              12               1 int[] D main test.d:4
 */

void main() {
    import std.stdio;

    int[] arr = [1, 1, 1];
    arr.reserve(512);

    foreach (i ; 0..20) // Just changing the number of elements
        arr ~= 42;
}

/*
 * bytes allocated, allocations, type, function, file:line
 *              80              20 int[] D main test.d:8
 *              12               1 int[] D main test.d:4
 */

void main() {
    import std.stdio;

    int[] arr = [1, 1, 1];
    // Same as above, without reserve

    foreach (i ; 0..20)
        arr ~= 42;
}

/*
 * bytes allocated, allocations, type, function, file:line
 *              80              20 int[] D main test.d:8
 *              12               1 int[] D main test.d:4
 */

As one can see there seem to be absolutely no difference in allocations wether we reserve or not. I've ran more experiences, reserving way less or more than I appened to no avail: allocations seem to just ignore it.

Isn't the point of .reserve to perform preallocation?

July 14, 2016
On Thursday, July 14, 2016 07:20:46 cym13 via Digitalmars-d-learn wrote:
> As one can see there seem to be absolutely no difference in allocations wether we reserve or not. I've ran more experiences, reserving way less or more than I appened to no avail: allocations seem to just ignore it.
>
> Isn't the point of .reserve to perform preallocation?

Whatever the profiler is telling you, it's clearly not actually telling you whether an allocation took place, and that's easy to test. For instance, let's change your example to

void main()
{
     import std.stdio;

     int[] arr;
     arr.reserve(50);
     writefln("capacity: %s", arr.capacity);

     immutable limit = cast(int)(arr.capacity + 2);
     foreach (i ; 0 .. limit)
     {
         if(append(arr, i))
             writefln("reallocation occurred: %s", i);
     }
}

bool append(ref int[] arr, int value)
{
    auto before = arr.ptr;
    arr ~= value;
    return arr.ptr !is before;
}

When I run it on my machine, I get

capacity: 63
reallocation occurred: 63

But if I change the code to

void main()
{
     import std.stdio;

     int[] arr;
     writefln("capacity: %s", arr.capacity);

     foreach (i ; 0 .. 63)
     {
         if(append(arr, i))
             writefln("reallocation occurred: %s", i);
     }
}

bool append(ref int[] arr, int value)
{
    auto before = arr.ptr;
    arr ~= value;
    return arr.ptr !is before;
}

so that it doesn't call reserve, and it just goes to 50 (since capacity is 0 to begin with), then it prints

capacity: 0
reallocation occurred: 0
reallocation occurred: 3
reallocation occurred: 7
reallocation occurred: 15
reallocation occurred: 31

So, reserve is definitely doing its job. My guess is that a GC function related to allocation occurs, which is why the GC profiler decides that allocation has occurred. I don't know. But if you look at the array itself, reserve is clearly doing its job. So, the profiler may need a bug report (I don't know much of anything about how the GC profiler works, so I don't know if this behavior is expected or not, though it certainly seems wrong), but from what I can see, reserve is not buggy.

- Jonathan M Davis

July 14, 2016
On Thursday, 14 July 2016 at 09:29:10 UTC, Jonathan M Davis wrote:
> On Thursday, July 14, 2016 07:20:46 cym13 via Digitalmars-d-learn wrote:
>> [...]
>
> Whatever the profiler is telling you, it's clearly not actually telling you whether an allocation took place, and that's easy to test. For instance, let's change your example to
>
> [...]

Thanks opened an issue for this https://issues.dlang.org/show_bug.cgi?id=16280