call by address vs. call by value

E

Erik

On Tue, 10 Feb 2004 13:49:46 GMT, the right honourable
[ Don't top-post, please. ]
*Ideally* call by address is faster because call by value makes a new copy
of the argument everytime you call the function.
Call by address does no copies instead pass the address of the variable as
is.

That is the theory, based on a very restricted view of a rather
old-fashioned kind of implementation, with no arguments passed in
registers and rather larger objects than pointers. Actual practice
doesn't always agree with this theory.
In fact, in practice, which objects will be faster passed as pointers
and which are faster passed directly depends entirely on the
architecture, the compiler, and possibly even on the generation of the
architecture (i.e., it could differ between a Pentium II and a Pentium
III). The only way to know which is best for you is to measure, and not
to assume that your measurements are correct for others.
Even then, in most cases the difference between pointer and value
passing is likely to be dwarfed by algorithmic choices. If passing a
pointer makes calling the function slightly faster, but actually doing
anything inside the function slower, more complicated, and more error-
prone, only a fool uses the pointer. Ditto vice versa.

Richard

i think one only can explain this speed difference if one looks at the
processor in question and to the assembler code involved.

Which would bring the question/answer off-topic.


frgr
Erik
 
C

Christian Bau

Grumble said:
I thought that C defined only call by value, and that call by address
was merely mimicked by passing the value of a pointer to an object.

Perhaps I misunderstood?

The topic nazis were asleep.

Yes, there is no such thing as "call by address" in C, so the original
question was completely OT.
 
E

Erik

On 10 Feb 2004 04:35:52 -0800, the right honourable
Why is "call by address" faster than "call by value"?

Once more:

I suspect , you look upon this matter in a wrong way.

Why is a bolt better than a nail ?

As we say in dutch: you compare apples and pears.

Call by address means, that the parameter passed to a function is a
pointer, or a memory address.
Apparently, your function needs an address. That was your choice when
you wrote the function. Could be the address of a 10 kb string or of
an integer.

Call by value means that the contents of a piece of memory is passed
as a parameter to the function and thereby duplicated for this
purpose.
Could be an integer, a floating point number, a whole 10 kb string.
Again your decision as a programmer.
It's irrelevant, if the one is faster than the other, because both
have a specific function, their own place in the universe.

And then: what if the value is an address ? then both are equally
speedy :)
Could be that you need to work on the address inside the function...
who knows ?

Or what if the size of an address is the same as the size of the value
the address points to ?

If you need some integer inside a function, you have to decide if you
need to work on the original data, or on/with a copy of it.
If you have to work on a 10kb data structure, inside a 100x loop, you
do not want to pass all 10k into the function.
But maybe you have to...

frgr
Erik
 
G

glen herrmannsfeldt

Erik wrote:

(snip regarding call by address vs. call by value)
i think one only can explain this speed difference if one looks at the
processor in question and to the assembler code involved.
Which would bring the question/answer off-topic.

You could try comp.arch, where processor dependence is on topic.

-- glen
 
A

Arthur J. O'Dwyer

Colloquially, I usually use the terms "pass by value" and "pass by
name" (or reference, or pointer...although using "reference" can be
problematic in C++) /in close conjunction/ with the object being
passed that way.

While your statement can be read as correct, I'll nitpick over
the implied equivalence of "pass by name" and "pass by reference,"
which are very different things! See Google Groups for a number
of gigantic threads on the subject of what constitutes pass by
value/reference/copy-and-return/name/text/lazy-evaluation, et al.
C, C++, Java, and friends generally have no built-in equivalent
to pass-by-name. [The answer to your unasked question will be found
in Google Groups.]

-Arthur
 
D

Dik T. Winter

>
> I think Dik's point is that with call by address, you have to jump to that
> address to get the data. If that data happened to be out of segment, or in
> paged memory, you could get a bad performance hit.

I think this was the case with early versions of IBM's AIX on the RS6000.
(If I remember right, a pointer consisted of 32 bits, a 16 bit segment
pointer and a 16 bit relative pointer. So to load a value you first
needed to load the segment pointer and next the relative pointer before
you could load the value. For something passed by value, the
relative pointer was constant and the segment pointer was already in a
register. But this is an extreme situation of the one below.)

Another possibility is if you have a processor that has insufficient
registers. To pick up a value from a struct passed by value the
compiler probably knows the address relative to the frame pointer (see,
this becomes highly machine dependent...), but you need only one load
operation to load the value. To get a similar value from a struct
passed by reference, first the address has to be loaded and next
(using that address and the field offset), the field. Two load
operations. If you use a lot of values that may be more expensive
than a single initial copy. I know of one Fortran compiler (where
parameters are passed by reference or by copy-in, copy-out, depending
on the discretion of the compiler), where the compiler sometimes
decided to make (within the routine) a local copy, which was copied
back at the end.
> The other point is that most architectures have registers. Passing values
> in registers is generally way faster than using pointers.

Indeed. And in that case pass by value is almost certainly faster.
Moreover, if there are enough registers to pass all arguments by
value, and to store all local variables, the compiler may decide to
dispense of setting up a new stack frame, and so the code comes close
to inlined code which is much faster.

Consider the following two implementations of 'max', using standard C
pass by value, or (what I understand here) pass by reference:

int max(int a, int b) { return (a > b ? a : b);}
int max(int *a, int *b) { return (*a > *b ? *a : *b);}

Consider the call "max(p, q)" vs. "max(&p, &q)". Assume a naive
stackbased compiler. And see what the code would do. Consider
every load and every store as a copy operation...
 
J

Jack Klein

http://www.cwi.nl/~dik/

Hello

Dik and Thomas, I didn't understand your point?

When calling by address the only thing that is being copied is the address
of the variable that you're accessing by address.
That applies to structures or any other variable.

Whereas when calling by value, a copy of the structure will be made before.

Sometimes the pointer is bigger than the object. And sometimes, even
if the object is larger than the data, the way you access the data via
the pointer might create more overhead than accessing a local copy
that was passed by value.
 
J

Jack Klein

You have to explain this further, because on the face of it, it
makes no sense.

Why do you have to copy less if you have a copy as opposed to a
reference (or pointer)? Are you talking about moving things between
registers? Memory locations?

No, he's talking about the total number of memory references including
the function call and the body of the function.

Let's assume a more-or-less typical architecture where function
arguments and local variables are accessed by offset from some sort of
frame pointer register in the processor, examples EBP in a Pentium or
R13 in an ARM.

Now consider a situation where there are not enough registers
available to cache the pointer in a register.

For every access to a member of the struct passed by a pointer, the
compiler must generate two instructions and two memory accesses:

load address_register, *(frame_ptr + struct_ptr_offset)
load data_register, *(address_register + member_offset)

On the other hand, if a copy of the structure is passed, it only
requires one instruction and memory access:

load data_register, *(frame_ptr + struct_offset + member_offset)

If you make many references to members of the structure in the called
function, the extra execution time in the called function may greatly
exceed the time required to copy the struct for passing by value.

Of course the called function can define a local object of the struct
type and initialize by copying from the passed pointer. And in some
cases that is the best option. But in other cases this amounts to
putting a band-aid on what should have been pass by value because
someone automatically believed that "passing a pointer is ALWAYS
better than passing by value."

In general it is the sort of micro-optimization that should only be
performed once the program works correctly but too slowly, and a tool
like a profiler has indicates that this a bottle neck.
 
N

Nick Landsberg

I think the moral of all of this thread is that there is no
black and white, only various shades of grey.

You have to know what you are doing and why
(and what your implementation is doing and why)
in order to make a reasoned choice.
Most times, it won't matter in the grand scheme
of things. But when you DO need to make this
kind of optimization, you need to understand
the implications of the decision, both on your
current platform and possible future platforms.
A hard and fast rule just doesn't cut it in all
cases.

Pass by value is not ALWAYS the correct choice
and pass by reference is not ALWAYS the correct choice.

The previous posts in this thread have been extremely
enlightening about the tradeoffs. Life, and programming,
is a series of tradeoffs.
 
E

E. Robert Tisdale

Jack said:
Sometimes the pointer is bigger than the object.
And sometimes, even if the object is larger than the data,
the way you access the data via the pointer
might create more overhead
than accessing a local copy that was passed by value.

What would really be nice is an example (a simple benchmark)
that illustrated this effect for objects of different sizes
and measured the "break-even" size for user defined types (structs).
 
T

Thomas Stegen CES2000

Jack said:
Now consider a situation where there are not enough registers
available to cache the pointer in a register.

This was the case I did not see (Why on earth not ;).

Thanks.
 
R

Richard Bos

E. Robert Tisdale said:
What would really be nice is an example (a simple benchmark)
that illustrated this effect for objects of different sizes
and measured the "break-even" size for user defined types (structs).

It would, at first glance, indeed look like this would be useful.
However, its actual value would be greatly diminished by the fact that
the measurements would vary greatly depending on platform,
implementation, and probably even compiler options. In short, you could
demonstrate the presence of the effect; but the break-even size pointed
at in the example could be made invalid by simply using -opt:hi instead
of -opt:medium, or by running it on a Z90 Mk. 4 instead of a Z90 Mk. 3.

Richard
 
L

Leor Zolman

Colloquially, I usually use the terms "pass by value" and "pass by
name" (or reference, or pointer...although using "reference" can be
problematic in C++) /in close conjunction/ with the object being
passed that way.

While your statement can be read as correct, I'll nitpick over
the implied equivalence of "pass by name" and "pass by reference,"
which are very different things! See Google Groups for a number
of gigantic threads on the subject of what constitutes pass by
value/reference/copy-and-return/name/text/lazy-evaluation, et al.
C, C++, Java, and friends generally have no built-in equivalent
to pass-by-name. [The answer to your unasked question will be found
in Google Groups.]

"unasked question..." sounds like some sort of Zen koan ;-)

If you mean my wondering about how "pass by value" is defined in C
(and I first used the term "call by value" inadvertently; I'm only
talking about argument passing), I've been trying to nail that down
from the Standard, and so far I've been unable to locate any use of
"pass by" anything at all. I've also been told, in a private
discussion, that in the context of C the term "call by value" is
meaningless (this time I do mean "call"), yet ironically there's an
index entry for it in the Standard (it is the only result I get from
searching for "call by" using Acrobat Reader 6's find feature), but I
honestly have not been able to reason out exactly which paragraph of
section 6.5.2.2 it is referring to!

The conclusion I'm drawing from this so far, and this situation is
similar to the one I ran into in an attempt to pin down the precise
meaning of the standalone word "prototype" in the /C++/ Standard (my
conclusion there was that folks are free to use it to mean just about
anything they want, because the term is not specifically defined, and
only /used/ within the phrase "function prototype scope" borrowed from
the C Standard), is that it would not be unreasonable to interpret any
colloquial use of "pass by name", "pass by reference" and "pass by
address" /in the context of C/ to be effectively synonymous. Of
course, one has to consider the source, and the context, but that's
precisely what I try to do when answering a question. I'm on a
learning curve, here...
-leor


Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
R

Richard Bos

Leor Zolman said:
is that it would not be unreasonable to interpret any
colloquial use of "pass by name", "pass by reference" and "pass by
address" /in the context of C/ to be effectively synonymous.

Almost. In colloquial use, I would consider "pass by address" and "pass
by reference" to be synonymous with "pass a pointer to", with the
proviso that "pass by reference" is ambiguous if C++ gets involved,
which it sometimes does even though it shouldn't.
"Pass by name", however, is something else entirely, and something we
would do well to keep far away from. Here there be dragons. Basically,
"pass by name" is similar, yet dissimilar, to what C does with macros,
with all the strengths those have, and all its dangers as well.

Richard
 
D

Dik T. Winter

> "Pass by name", however, is something else entirely, and something we
> would do well to keep far away from. Here there be dragons. Basically,
> "pass by name" is similar, yet dissimilar, to what C does with macros,
> with all the strengths those have, and all its dangers as well.

I have used it much to my advantage, but not in C of course.
(Jensen's device of course.) The difference with macro's is
of course that macro's are completely compile-time, call-by-name
is not.

(And then there is of course that article in Datamation where the
language Babbage was explained. It had call-by-telephone for
long-distance parameters.)
 
E

E. Robert Tisdale

Richard said:
It would, at first glance, indeed look like this would be useful.
However, its actual value would be greatly diminished by the fact that
the measurements would vary greatly depending on platform,
implementation, and probably even compiler options.
In short, you could demonstrate the presence of the effect;
but the break-even size pointed at in the example
could be made invalid by simply using -opt:hi instead of -opt:medium,
or by running it on a Z90 Mk. 4 instead of a Z90 Mk. 3.

It sure would be nice to have an example that we could use
to confirm or refute all of this conjecture. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top