About ref used for performance reasons with struct

Paulo Pinto pjmlp at progtools.org
Mon Feb 11 02:21:29 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.

How does this work in the context of modular programming?

Does the compiler generate multiple code for each case, to make 
the code work regardless of what is decided at the call site?

Or is the code written in a canonical form inside the module, 
which gets to be rewritten when all modules are linked into the 
final binary?

By modules I mean the case where you only have a .di file + 
binary code for the module. For me the right form to distribute 
libraries.

--
Paulo


More information about the Digitalmars-d mailing list