Array append performance (Was: Re: Lisp like lists and a problem with TANGO fromStringz)
Oskar Linde
oskar.lindeREM at OVEgmail.com
Mon Mar 3 10:05:42 PST 2008
bearophile wrote:
> To: Newsgroups: digitalmars.D
> Subject: Re: Lisp like lists and a problem with TANGO fromStringz
>
> Oskar Linde>Here is a way to reserve space for arrays:<
>
> I did try a function equal to that one, but have you timed it? My timing results don't show any advantage of using such reserve.
There are more advantages to do it than speed. Memory fragmentation and
wastage for example.
<snip>
> OUTPUT TIMINGS:
>
> DMD 1.026, N = 12_000_000:
> append: 3.3 s
> reserve + append: 3.3 s
> allocate + assign: 1.0 s
It is hard to draw too many conclusions from such a simple test. For one
thing, the DMD GC will on array appends try to grow the allocated GC
chunk without reallocating. In an application such as this (with
virtually no memory fragmentation), there is a good chance that it is
able to do that almost all the time.
DMD/GDC also seems unable to inline the _d_arrayappendcTp call which
would be one reason for the rather poor performance overall.
There are cases where the reallocation helps though, even though the
performance overall is embarrassing compared to not appending.
GDC 0.24, N = 120_000_000:
append: 9.3 s
reserve + append: 5.3 s
allocate + assign: 1.3 s
(Also note that append in this case wastes 168 MB memory compared to
reserve+append (*))
It is also slightly faster for small arrays, where the GC bucket
limitation prevents in place growing from happening:
GDC 0.24, N = 512:
append: 26 µs
reserve + append: 23 µs
allocate + assign: 1.7 µs
----
*) There seems to be a bug (or it might be by design) that the GC on
appending to an array sometimes allocates up to 3x the required memory
(to me, it seems anything above 2x is seriously overkill). The line in
question is in internal/gc/gc.d in Phobos, where the correct line is
commented out:
//long mult = 100 + (1000L * size) / (6 * log2plus1(newcap));
long mult = 100 + (1000L * size) / (log2plus1(newcap));
So, for example, appending one int to a 1MB int[] array, could result in
an array with 3MB reserved space. Or appending a single int to a 74MB
array results in a 184 MB array. Something to look out for.
--
Oskar
More information about the Digitalmars-d
mailing list