On 1/20/22 17:35, forkit wrote:

> module test;
> @safe

Does that make just the following definition @safe or the entire module @safe? Trying... Yes, I am right. To make the module safe, use the following syntax:

@safe:

>      idArray.reserve(recordsNeeded);
[...]
>             idArray ~= x; // NOTE: does NOT appear to register with
> -profile=gc

Because you've already reserved enough memory above. Good.

>      int[][int][] records;
>      records.reserve(numRecords);

That's good for the array part. However...

>          // NOTE: below does register with -profile=gc
>          records ~= [ idArray[i] : valuesArray[i] ];

The right hand side is a freshly generated associative array. For every element of 'records', there is a one-element AA created. AA will need to allocate memory for its element. So, GC allocation is expected there.

>      string[] formattedRecords;
>      formattedRecords.reserve(recArray.length);
[...]
>          // NOTE: below does register with -profile=gc
>          formattedRecords ~= id.to!string ~ values.format!"%(%s,%)";

Again, although 'formattedRecords' has reserved memory, the right hand side has dynamic memory allocations.

1) id.to!string allocates

2) format allocates memory for its 'string' result (I think the Appender report comes from format's internals.)

3) Operator ~ makes a new string from the previous two

(Somehow, I don't see three allocations though. Perhaps an NRVO is applied there. (?))

I like the following better, which reduces the allocations:

        formattedRecords ~= format!"%s%(%s,%)"(id.to!string, values);

>      foreach(ref rec; formattedRecords)
>          file.writeln(rec);

The bigger question is, why did 'formattedRecords' exist at all? You could have written the output directly to the file. But even *worse* and with apologies, ;) here is something crazy that achieves the same thing:

void ProcessRecords
(in int[][int][] recArray, const(string) fname)
{
    import std.algorithm : joiner;
    auto toWrite = recArray.map!(e => e.byPair);
File("rnd_records.txt", "w").writefln!"%(%(%(%s,%(%s,%)%)%)\n%)"(toWrite);
}

I've done lot's of trial and error for the required number of nested %( %) pairs. Phew...

Ali

Reply via email to