www.digitalmars.com         C & C++   DMDScript  

D - pass by reference or value?

reply imr1984 <imr1984_member pathlink.com> writes:
As structs are value types, should i always pass a struct using one of the
reference qualifiers (i hope thats the right name) ? for example:

void myFunc(in MyStruct ms)
{
}

Or should i just let it pass by value?

void myFunc(MyStruct ms)
{
}

I was thinking that with the advent of the 64 bit processors which have 127
general purpose registers, it might just be faster to pass it by value, but i
might be wrong. What do you think?
Jan 07 2004
parent reply Ilya Minkov <minkov cs.tum.edu> writes:
If you read the manual,

 void myFunc(in MyStruct ms)

is absolutely the same as
 void myFunc(MyStruct ms)

because where no qualifier is specified, in is implicit. In only denotes semantics, but not whether the struct would be passed by value or not. Depending on the size of the struct, compiler should be able to choose automatically, whether this is by value, or by constant reference. I'm not sure whether the current one can draw any wisdom of the struct size, but it is just the beginning, right?
 I was thinking that with the advent of the 64 bit processors which have 127
 general purpose registers, it might just be faster to pass it by value, but i
 might be wrong. What do you think?

I think if you are talking of structs up to 8 bytes, it might already faster to pass them by value. With newer architectures, the margin would probably move towards larger numbers, but it is up to compiler to decide, so that code would stay portable and would not loose on performance. Same with alignment. -eye
Jan 07 2004
next sibling parent imr1984 <imr1984_member pathlink.com> writes:
In article <bthren$2p6n$1 digitaldaemon.com>, Ilya Minkov says...
If you read the manual,

 void myFunc(in MyStruct ms)

is absolutely the same as
 void myFunc(MyStruct ms)

because where no qualifier is specified, in is implicit. In only denotes semantics, but not whether the struct would be passed by value or not. Depending on the size of the struct, compiler should be able to choose automatically, whether this is by value, or by constant reference. I'm not sure whether the current one can draw any wisdom of the struct size, but it is just the beginning, right?
 I was thinking that with the advent of the 64 bit processors which have 127
 general purpose registers, it might just be faster to pass it by value, but i
 might be wrong. What do you think?

I think if you are talking of structs up to 8 bytes, it might already faster to pass them by value. With newer architectures, the margin would probably move towards larger numbers, but it is up to compiler to decide, so that code would stay portable and would not loose on performance. Same with alignment. -eye

"Depending on the size of the struct, compiler should be
able to choose automatically, whether this is by value, or by constant 
reference."

so where is the threshold value for this decision? Where does it say this in the spec? By constant reference, do you mean that if the struct is passed by reference then the function isnt allowed to change it?
Jan 08 2004
prev sibling parent reply imr1984 <imr1984_member pathlink.com> writes:
In article <bthren$2p6n$1 digitaldaemon.com>, Ilya Minkov says...
If you read the manual,

 void myFunc(in MyStruct ms)

is absolutely the same as
 void myFunc(MyStruct ms)

because where no qualifier is specified, in is implicit. In only denotes semantics, but not whether the struct would be passed by value or not. Depending on the size of the struct, compiler should be able to choose automatically, whether this is by value, or by constant reference. I'm not sure whether the current one can draw any wisdom of the struct size, but it is just the beginning, right?
 I was thinking that with the advent of the 64 bit processors which have 127
 general purpose registers, it might just be faster to pass it by value, but i
 might be wrong. What do you think?

I think if you are talking of structs up to 8 bytes, it might already faster to pass them by value. With newer architectures, the margin would probably move towards larger numbers, but it is up to compiler to decide, so that code would stay portable and would not loose on performance. Same with alignment. -eye

"Depending on the size of the struct, compiler should be
able to choose automatically, whether this is by value, or by constant 
reference."

so where is the threshold value for this decision? Where does it say this in the spec? By constant reference, do you mean that if the struct is passed by reference then the function isnt allowed to change it?
Jan 08 2004
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
imr1984 wrote:
 "Depending on the size of the struct, compiler should be 
 
able to choose automatically, whether this is by value, or by constant 
reference."

so where is the threshold value for this decision? Where does it say this in the spec? By constant reference, do you mean that if the struct is passed by reference then the function isnt allowed to change it?

It's the other way around, actually. The compiler would look at how you use it, and work out how to implement it appropriately. If you pass a big struct in, and you don't alter it, then the compiler can implement it as passing by const reference. If you alter it, then it has no choice but to pass by value. The compiler should always be able to pass by reference if you use out or inout. In other words, don't think about it. The compiler knows enough to decide on its own. -- andy
Jan 08 2004
parent reply Georg Wrede <Georg_member pathlink.com> writes:
In article <btjq3f$2nna$1 digitaldaemon.com>, Andy Friesen says...
It's the other way around, actually.  The compiler would look at how you 
use it, and work out how to implement it appropriately.  If you pass a 
big struct in, and you don't alter it, then the compiler can implement 
it as passing by const reference.  If you alter it, then it has no 
choice but to pass by value.  The compiler should always be able to pass 
by reference if you use out or inout.

In other words, don't think about it.  The compiler knows enough to 
decide on its own.

This sounds as if the out and inout were superfluous. Which, I think, just deepens the original question.
Jan 10 2004
parent Ilya Minkov <minkov cs.tum.edu> writes:
Georg Wrede wrote:

 This sounds as if the out and inout were superfluous.
 Which, I think, just deepens the original question.

They are not superfluous, since they change most importantly the semantics - helping to write correct and self-documenting code - and by the way also applicable optimisations. -eye
Jan 10 2004
prev sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
imr1984 wrote:

 so where is the threshold value for this decision? Where does it say this in
the
 spec? By constant reference, do you mean that if the struct is passed by
 reference then the function isnt allowed to change it?

Threshold need not be explicit. And would definately be optimally chosen for each platform. Besides, i don't know how it is implemented now! The purpose of the current compiler is to implement the specification correctly. Being good comes next. By constant reference, i mean that the original cannot be modified. To modify it, the compiler would need to automatically generate a local copy within the function to simulate a pass by value. This cannot affect calling convention, since it has to be completely identifiable by a prototype. However, this only works so with value types, such as primitives and structs. Classes and array slices are different, in the sense that they always have a reference semantics - you can mutate them but you cannot reseat them. Bottom line is: let design drive your code, and let platform-specific performance considerations to the compiler. Even if you might be unsatisfied by decisions the current one could make, soon this will pay off, with transition to better compilers and then 64-bit systems. -eye
Jan 10 2004