toString refactor in druntime

Jonathan Marler via Digitalmars-d digitalmars-d at puremagic.com
Thu Oct 30 11:53:59 PDT 2014


>
> Before we start ripping apart our existing APIs, can we show 
> that the performance is really going to be so bad? I know 
> virtual calls have a bad reputation, but I hate to make these 
> choices absent real data.
>
> For instance, D's underlying i/o system uses FILE *, which is 
> about as virtual as you can get. So are you avoiding a virtual 
> call to use a buffer to then pass to a virtual call later?
>
I think its debatable how useful this information would be but 
I've written a small D Program to try to explore the different 
performance statistics for various methods.  I've uploaded the 
code to my server, feel free to download/modify/use.

Here's the various methods I've tested.
/**
    Method 1: ReturnString
              string toString();
    Method 2: SinkDelegate
              void toString(void delegate(const(char)[]) sink);
    Method 3: SinkDelegateWithStaticHelperBuffer
              struct SinkStatic { char[64] buffer; void 
delegate(const(char)[]) sink; }
	     void toString(ref SinkStatic sink);
    Method 4: SinkDelegateWithDynamicHelperBuffer
              struct SinkDynamic { char[] buffer; void 
delegate(const(char)[]) sink; }
	     void toString(ref SinkDynamic sink);
	     void toString(SinkDynamic sink);

  */

Dmd/No Optimization (dmd dtostring.d):

RuntimeString run 1 (loopcount 10000000)
   Method 1     : 76 ms
   Method 2     : 153 ms
   Method 3     : 156 ms
   Method 4ref  : 157 ms
   Method 4noref: 167 ms
StringWithPrefix run 1 (loopcount 1000000)
   Method 1     : 159 ms
   Method 2     : 22 ms
   Method 3     : 80 ms
   Method 4ref  : 80 ms
   Method 4noref: 83 ms
ArrayOfStrings run 1 (loopcount 1000000)
   Method 1     : 1 sec and 266 ms
   Method 2     : 79 ms
   Method 3     : 217 ms
   Method 4ref  : 226 ms
   Method 4noref: 222 ms

Dmd/With Optimization (dmd -O dtostring.d):
RuntimeString run 1 (loopcount 10000000)
   Method 1     : 35 ms
   Method 2     : 67 ms
   Method 3     : 67 ms
   Method 4ref  : 72 ms
   Method 4noref: 70 ms
StringWithPrefix run 1 (loopcount 1000000)
   Method 1     : 154 ms
   Method 2     : 9 ms
   Method 3     : 86 ms
   Method 4ref  : 63 ms
   Method 4noref: 65 ms
ArrayOfStrings run 1 (loopcount 1000000)
   Method 1     : 1 sec and 252 ms
   Method 2     : 37 ms
   Method 3     : 191 ms
   Method 4ref  : 193 ms
   Method 4noref: 201 ms


I would like to make a note that passing around a stack allocated 
buffer to the various toString methods along with a sink delegate 
may not get much performance benefit.  One reason is because the 
logic can get a little hairy when trying to decide if the buffer 
is large enough for the string (see my code on ArrayOfStrings) 
which creates more code which can slow down the processor simply 
because there is more "code" memory the processor has to manage.  
Also note that adding a helper method to the buffer/sink delegate 
doesn't help at all since this is equivalent to passing around 
the delegate (meaning you could just create the Buffered sink 
that calls the real delegate when it gets full and pass around 
it's own sink delegate).


More information about the Digitalmars-d mailing list