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
<deadal...@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/opufykfxwkkjchqcw...@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.