About ref used for performance reasons with struct

Minas Mina minas_mina1990 at hotmail.co.uk
Mon Feb 11 04:18:17 PST 2013


On Monday, 11 February 2013 at 06:52:33 UTC, deadalnix wrote:
> 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.

+1

It's really ugly to write "const ref Blah blah" all the time when 
the compiler could it.


More information about the Digitalmars-d mailing list