Best way to clear dynamic array for reuse

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jul 13 05:45:31 PDT 2016


On Wednesday, July 13, 2016 11:59:18 Miguel L via Digitalmars-d-learn wrote:
> I am using a temporary dynamic array inside a loop this way:
> A[] a;
> for(....)
> {
> a=[]; //discard array contents
> ... appends thousand of elements to a
> ... use a for some calculations
> }
>
> I would like to know which would be the best way to clear a
> contents avoiding reallocations, as there seems to be lots of
> garbage collection cycles taking place.
>
> The options would be:
>
> a=[];
> a.length=0;
> a=null;
> ...
> any other?
>
> Can you help me please?

a = [];

and

a = null;

both set the .ptr property of an array to null, and the length to 0. Setting
the length to 0, just sets the length to 0. Regardless, appending after any
of those operations is going to result in allocating memory, because the
dynamic array has no unused memory to expand into. The GC determines whether
it can append to a dynamic array without allocating based on whether that
dynamic array's last element is the last element in the block of memory that
the dynamic array refers to which has been used by any dynamic array. It
does not keep track of how many arrays refer to the same memory block or
where in the memory block they refer to. So, if the dynamic array that
you're trying to append to does not refer to the last element in that block
of memory which hasn't been used, then the GC has to assume that another
dynamic array might refer to it. So, it won't expand into that memory and
will instead reallocate. And because of that mechanic, in general, trying to
"clear" a dynamic array doesn't work.

However, if you are certain that there are no other dynamic arrays refering
to the same memory, then you can tell the GC that by using assumeSafeAppend.
e.g.

a.length = 0;
a.assumeSafeAppend();

And then the GC will think that the last element in a (which would be no
element in this case) is the last used point in the block of memory pointed
to by the dynamic array, and so it won't reallocate when you append. The big
caveat here, of course, is that you have to be sure that there are no other
dynamic arrays referring to the memory after a, or you'll be stomping on
their memory when you append to a. But as long as you're sure that no other
dynamic arrays refer to that memory, then you're fine.

If you want an array type where you can clear out its elements and affect
all other references to that array as well, then the built-in dynamic arrays 
won't cut it, and you'll need to use something like std.container.Array.

If you haven't yet, I would advise reading

http://dlang.org/d-array-article.html

since it goes into detail on how D's dynamic arrays work - though it uses
the wrong terminology and refers to the GC-allocated buffer that the dynamic
array points to as if it were the dynamic array, and calls the dynamic array
a slice, whereas the official terminology is that T[] is a dynamic array (no
matter what memory it refers to), and if it's non-null, then it's a slice of
whatever memory it points to. However, the memory that it points to is just
the memory that it points to. It has no special name, even if it's
GC-allocated. So, even if T[] is a slice of malloc-ed memory or of a static
array, it's still a dynamic array (though in that case, appending to it will
always reallocate, since the GC can't grow a dynamic array unless it points
to memory allocated by the GC for dynamic arrays). But in spite of the
slight terminology problem, it's a great article, and a must-read for anyone
serious about D.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list