About ref used for performance reasons with struct

deadalnix deadalnix at gmail.com
Sun Feb 10 22:52:28 PST 2013


Ok, We have 2 usages of ref : when you actually need to modify 
informations, and for performance reasons. Let's talk about the 
second one.

Passing by ref to improve performance is not ideal. First this is 
quite hard to know when it is actually faster to pass by ref and 
to pass by value, especially in generic code. Secondly it is easy 
to forget to use ref at some location, and a lot of small 
performance improvement are lost in the process. Finally, this 
may be error prone.

I'm thinking about it for a while now and I'm now convinced that 
we should allow the compiler to do that job for us. Let me 
explain.

When a function accept a struct, the compiler is free to use that 
function, or an altered one taking a reference as parameter. Here 
are some rules the compiler can use to know which one to call 
from callee side :

The caller is free to call the ref version of the function unless 
(rules evaluate in order) :
  - The argument is an rvalue (in such case, no postblit is 
executed as well).
  - The argument is shared.
  - The argument's postblit in not pure (weakly).

The callee isn't modified for the vanilla function, but must 
create a local copy of the argument in the following reasons in 
the ref version :
  - The argument is binded to a mutable ref.(even as hidden 
argument as for member method).
  - The argument is actually modified.
  - address of anything coming from the struct is taken.

The compiler is free to apply such treatment only in a branch of 
the callee, ie :

// Compiler choose to create an alternative ref version for 
performance.
void foo(MyStruct s) {
     if(condition) {
         // Operation require a copy to not alter what the caller 
see.
         // A s is copied on stack and postblit is called.
         s.field = 5;
     } else {
         // No operation requiring local copy is performed.
         // No local copy is created.
     }
}

The compiler is however disallowed to create multiple copies in 
the callee. If several branches requires it, then the copy have 
to be made in a common branch.

Note that the compiler don't HAVE to do this, but is allowed to. 
Modifying the spec in such way allow the compiler to avoid many 
copies of struct let us get rid of most ref parameters, keeping 
them for what they really are for.


More information about the Digitalmars-d mailing list