assumeSafeAppend on slice of static array?

monarch_dodra via Digitalmars-d digitalmars-d at puremagic.com
Tue Apr 22 12:00:05 PDT 2014


On Tuesday, 22 April 2014 at 18:52:44 UTC, Steven Schveighoffer 
wrote:
> On Tue, 22 Apr 2014 14:31:07 -0400, H. S. Teoh via 
> Digitalmars-d <digitalmars-d at puremagic.com> wrote:
>
>> On Tue, Apr 22, 2014 at 02:24:41PM -0400, Steven Schveighoffer 
>> via Digitalmars-d wrote:
>>> On Tue, 22 Apr 2014 14:10:30 -0400, H. S. Teoh via 
>>> Digitalmars-d
>>> <digitalmars-d at puremagic.com> wrote:
>>>
>>> >I'm going through some code and thinking of ways to reduce GC
>>> >pressure, and came across a bit that needed to append some 
>>> >items to
>>> >an array:
>>> >
>>> >	T[] args;
>>> >	lex.expect("(");
>>> >	args ~= parseSingleItem(lex);
>>> >	while (!lex.empty) {
>>> >		lex.expect(",");
>>> >		args ~= parseSingleItem(lex);
>>> >	}
>>> >	lex.expect(")");
>>> >	return computeResult(args);
>>> >
>>> >Now obviously, in the general case (with arbitrarily many 
>>> >number of
>>> >items) some GC allocations will be needed, but the most 
>>> >common
>>> >use-cases are actually only 1 or 2 items each time. 
>>> >Allocating lots
>>> >of small arrays seem to be rather wasteful, so I thought to 
>>> >use a
>>> >static array as a buffer instead.
>>> >
>>> >The question is, is there a way to take a slice of the 
>>> >static array,
>>> >set the length to zero, and append to it with ~= such that 
>>> >when it
>>> >runs out of space in the static buffer, it will reallocate a 
>>> >longer
>>> >array on the GC heap? Or is this a bad idea?
>>>
>>> TL;DR: Yes, use Appender :)
>>>
>>> The reason appending even works is because of the metadata 
>>> stored in
>>> the heap. Obviously, stack frames and fixed-length arrays do 
>>> not have
>>> this data.
>>>
>>> When that metadata cannot be found, it reallocates because 
>>> that's the
>>> only option.
>>>
>>> However, Appender, initialized with a static buffer, knows 
>>> the length
>>> of its data, and stores its own capacity, separate from the 
>>> heap.
>> [...]
>>
>> Unfortunately, the whole point of this exercise was to 
>> eliminate GC
>> allocations for small arrays -- but since Appender's 
>> implementation
>> allocates a private Data struct in its ctor, that kinda 
>> defeats the
>> purpose. For the common case of 1 or 2 items only, it doesn't 
>> seem like
>> Appender will perform any better, and it will introduce extra 
>> GC
>> allocations to boot.
>>
>> :-(
>
> I advocated a long time ago that Appender should have a 
> stack-based version.
>
> I still think that's the case. Because really what Appender has 
> as an advantage over builtin slices is that it keeps a local 
> copy of the capacity, so no heap metadata lookups need to 
> occur. It's not conceptually that much added.
>
> Of course, back then, I'm not sure we had @disable this(this), 
> which such an appender should have.
>
> -Steve

What I said in the other thread, my ScopeAppender is stack based. 
Very soon to being finished :)


More information about the Digitalmars-d mailing list