Sometimes 100 lines of code can fix your ctfe perf

Ali Çehreli acehreli at yahoo.com
Tue Aug 24 22:33:14 UTC 2021


On 8/24/21 1:14 PM, Paul Backus wrote:

 >> On Tuesday, 24 August 2021 at 16:58:26 UTC, Adam D Ruppe wrote:
 >>> On Tuesday, 24 August 2021 at 16:52:30 UTC, Ali Çehreli wrote:

 >>>>     auto s = format!"hello %s world %s"(a, b);
 >>>
 >>> yikes that's like the worst thing in the whole D world. brutally slow
 >>> by all metrics.

[...]

 > Internally, `format` uses `formattedWrite`
 > with an `Appender` as the output range [1]

That's what I thought. Additionally, some of my structs define 
toString() functions that work with a "sink" so they would be written 
into the buffer of an appender without extra string creation:

   https://dlang.org/library/std/format/write.html

To do even better, we could write the following function that reuses a 
static Appender object:

auto appendingFormatter(string fmt, string file = __FILE__, size_t line 
= __LINE__, Args...)(Args args) {
   import std.array : Appender;
   import std.format : formattedWrite;

   static Appender!(char[]) buffer;
   buffer.clear();
   buffer.formattedWrite!fmt(args);
   return buffer.data;
}

import std.stdio;

void main() {
   size_t total;

   enum N = 100;

   foreach (i; 0 .. N) {
     foreach (d; 0 .. N) {
       total += appendingFormatter!"hello %s world %s"(i, d).length;
       total += appendingFormatter!"goodbye %s moon %s"(i * 10, d / 
7).length;
     }
   }

   writeln(appendingFormatter!"An arbitrary value: %s"(total));

   const a = appendingFormatter!"%s"(42); const b = 
appendingFormatter!"%s"(43);
   // BUG: Fails.
   assert((a == "42") && (b == "43"));
}

Performance is awesome because there is almost no memory allocation.

Unfortunately, there is that bug on the last line of main because there 
is no __COLUMN__ or __ID__ or __COUNTER__ or etc. that would differ per 
__LINE__. Or, is there? Please? :)

Do you know a trick that would pass that assertion?

Ali




More information about the Digitalmars-d mailing list