About ref used for performance reasons with struct

deadalnix deadalnix at gmail.com
Tue Feb 12 09:33:07 PST 2013


On Monday, 11 February 2013 at 22:40:44 UTC, Dan wrote:
> On Monday, 11 February 2013 at 16:56:38 UTC, deadalnix wrote:
>> On Monday, 11 February 2013 at 16:51:22 UTC, Steven 
>> Schveighoffer wrote:
>>> On Mon, 11 Feb 2013 10:08:52 -0500, deadalnix 
>>> <deadalnix at gmail.com> wrote:
>>>
>>>> A good rule of thumb to know when to pass by ref for perf is 
>>>> :
>>>> - The struct is big, or contains mixed entities (floats and 
>>>> ints). 2*size_t seems like a good heuristic from my 
>>>> experience.
>>>
>>> Array slices are 2*sizeof(size_t).  I would expect them to be 
>>> always copied and not ref'd.
>>>
>>
>> First, they alway appears to be copied from the dev 
>> perspective. That why I put bunch of restrictions in the 
>> proposal.
>>
>> Second, slice are 2*size_t and are not mixed entities (from 
>> CPU perspective, pointer are integers). So I don't have 
>> numbers, but I expect slice to be faster when passed by copy 
>> than when passed by ref.
>
> The idea of compiler choosing the optimal between: 'T t' and 
> 'ref const(T) t' has been brought up a few times. Here is one 
> attempt at getting numbers to see where a cutoff might be.
>
> http://forum.dlang.org/thread/opufykfxwkkjchqcwgrg@forum.dlang.org
>
> Based on this, and to avoid the boilerplate of read accessors, 
> I use the following heuristic. If others have more friendly 
> ways I'd be interested.
>
> Thanks
> Dan
>
>
> /** Discriminates a pass type by its size
>  */
> template PrefersPassByRef(T) {
>   static if(isAssociativeArray!T || isDynamicArray!T) {
>     enum PrefersPassByRef = false;
>   } else static if(T.sizeof > 16 || hasAliasing!T)  {
>     enum PrefersPassByRef = true;
>   } else {
>     enum PrefersPassByRef = false;
>   }
> }
>
> /** Discriminates a pass type by its size
>  */
> template PreferredPassType(T) {
>   static if(PrefersPassByRef!T) {
>     enum PreferredPassType = `const ref `~T.stringof;
>   } else {
>     enum PreferredPassType = T.stringof;
>   }
> }
>
> /** Provides mixin for making a field read only.
>  *  For example mixin(ReadOnly!_fieldName) provides a getter 
> named fieldName.
>  */
> template ReadOnly(alias name) {
>   enum v = name.stringof;
>   enum p = name.stringof[1..$];
>   enum prefersReference = PrefersPassByRef!(typeof(name));
>   static if(prefersReference) {
>     mixin(`
> public @property auto ref `~p~`() const {
>   return `~v~`;
> }
> `);
>   } else {
>     mixin(`
> public @property auto `~p~`() const {
>   return `~v~`;
> }
> `);
>   }
> }

This is a lot o code and don't handle some cases. For instance

struct A {
     long a;
     double b;
}

is generally better passed by ref, where

struct A {
     long a;
     long b;
}

is better passed by value.


More information about the Digitalmars-d mailing list