linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* efficiency in passing a value to a function
@ 2007-04-04 17:13 Shriramana Sharma
  2007-04-04 18:27 ` Glynn Clements
  2007-04-04 18:38 ` Steve Graegert
  0 siblings, 2 replies; 11+ messages in thread
From: Shriramana Sharma @ 2007-04-04 17:13 UTC (permalink / raw)
  To: linux-c-programming

Hello.

Is providing an input to a function by constant reference more efficient 
than passing it by value? In what way.

For ex:

int addOne ( const & int inValue ) { return inValue + 1 ; }

vs:

int addOne ( int inValue ) { return inValue + 1 ; }

or:

void printThis ( const & int inValue ) { cout << inValue ; }

vs:

void printThis ( int inValue ) { cout << inValue ; }

I think passing as const & would be more efficient since passing by 
value would involve copying the value whereas passing by const & would 
skip this step. Am I right? Or is there something else?

Thanks in advance.

Shriramana Sharma.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-04 17:13 efficiency in passing a value to a function Shriramana Sharma
@ 2007-04-04 18:27 ` Glynn Clements
  2007-04-11 21:44   ` Adam Dyga
  2007-04-04 18:38 ` Steve Graegert
  1 sibling, 1 reply; 11+ messages in thread
From: Glynn Clements @ 2007-04-04 18:27 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: linux-c-programming


Shriramana Sharma wrote:

> Is providing an input to a function by constant reference more efficient 
> than passing it by value? In what way.

Passing a reference doesn't copy the value. This can be significant if
the value is large (i.e. a structure); for values which are no larger
than a pointer, it is unlikely to make any difference.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-04 17:13 efficiency in passing a value to a function Shriramana Sharma
  2007-04-04 18:27 ` Glynn Clements
@ 2007-04-04 18:38 ` Steve Graegert
  2007-04-05 12:05   ` Glynn Clements
  2007-04-08 14:45   ` Shriramana Sharma
  1 sibling, 2 replies; 11+ messages in thread
From: Steve Graegert @ 2007-04-04 18:38 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: linux-c-programming

Shriramana,

On 4/4/07, Shriramana Sharma <jamadagni@gmail.com> wrote:
> Hello.
>
> Is providing an input to a function by constant reference more efficient
> than passing it by value? In what way.
>
> For ex:
>
> int addOne ( const & int inValue ) { return inValue + 1 ; }
>
> vs:
>
> int addOne ( int inValue ) { return inValue + 1 ; }
>
> or:
>
> void printThis ( const & int inValue ) { cout << inValue ; }
>
> vs:
>
> void printThis ( int inValue ) { cout << inValue ; }
>
> I think passing as const & would be more efficient since passing by
> value would involve copying the value whereas passing by const & would
> skip this step. Am I right? Or is there something else?

I have seen many programs making use const reference parameters in
order to inform the compiler that the parameter is read-only, and
hence should be better optimized.

Unfortunately, this intent is at odds with the C++ language
definition. The const keyword says that the storage may not be
modified through the given name. What it does not say is that the
storage cannot be modified through some other name.

With the exception of variables directly declared const, which means
you can only initialize them, const is basically ineffective a
improving run-time performance. It does, however, catch errors in the
programming process.

	\Steve

--

Steve Grägert <steve@graegert.com>
Jabber    xmpp://graegerts@jabber.org
Internet  http://eth0.graegert.com, http://blog.graegert.com
-
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-04 18:38 ` Steve Graegert
@ 2007-04-05 12:05   ` Glynn Clements
  2007-04-05 13:02     ` Steve Graegert
  2007-04-08 14:45   ` Shriramana Sharma
  1 sibling, 1 reply; 11+ messages in thread
From: Glynn Clements @ 2007-04-05 12:05 UTC (permalink / raw)
  To: Steve Graegert; +Cc: Shriramana Sharma, linux-c-programming


Steve Graegert wrote:

> > I think passing as const & would be more efficient since passing by
> > value would involve copying the value whereas passing by const & would
> > skip this step. Am I right? Or is there something else?
> 
> I have seen many programs making use const reference parameters in
> order to inform the compiler that the parameter is read-only, and
> hence should be better optimized.
> 
> Unfortunately, this intent is at odds with the C++ language
> definition. The const keyword says that the storage may not be
> modified through the given name. What it does not say is that the
> storage cannot be modified through some other name.
> 
> With the exception of variables directly declared const, which means
> you can only initialize them, const is basically ineffective a
> improving run-time performance. It does, however, catch errors in the
> programming process.

Using a const qualifier still allows the compiler to optimise the
caller. E.g. if it computes a complex expression involving a variable,
passes a pointer/reference to that variable to a function, then
subsequently uses the result of the expression, it doesn't have to
re-compute the expression if the pointer/reference has a const
qualifier.

In any case, I suspect that the OP was talking primarily about passing
references rather than values, rather than about const qualifiers
per se.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-05 12:05   ` Glynn Clements
@ 2007-04-05 13:02     ` Steve Graegert
  2007-04-08 15:17       ` Shriramana Sharma
  0 siblings, 1 reply; 11+ messages in thread
From: Steve Graegert @ 2007-04-05 13:02 UTC (permalink / raw)
  To: Glynn Clements; +Cc: Shriramana Sharma, linux-c-programming

On 4/5/07, Glynn Clements <glynn@gclements.plus.com> wrote:
>
> Steve Graegert wrote:
>
> > > I think passing as const & would be more efficient since passing by
> > > value would involve copying the value whereas passing by const & would
> > > skip this step. Am I right? Or is there something else?
> >
> > I have seen many programs making use const reference parameters in
> > order to inform the compiler that the parameter is read-only, and
> > hence should be better optimized.
> >
> > Unfortunately, this intent is at odds with the C++ language
> > definition. The const keyword says that the storage may not be
> > modified through the given name. What it does not say is that the
> > storage cannot be modified through some other name.
> >
> > With the exception of variables directly declared const, which means
> > you can only initialize them, const is basically ineffective a
> > improving run-time performance. It does, however, catch errors in the
> > programming process.
>
> Using a const qualifier still allows the compiler to optimise the
> caller. E.g. if it computes a complex expression involving a variable,
> passes a pointer/reference to that variable to a function, then
> subsequently uses the result of the expression, it doesn't have to
> re-compute the expression if the pointer/reference has a const
> qualifier.
>
> In any case, I suspect that the OP was talking primarily about passing
> references rather than values, rather than about const qualifiers
> per se.

This might indeed be true.

If a programmer has chosen to pass a reference rather than a value,
even if no reference is actually required, intentions to improve
run-time performance come into mind.  It is much more intuitive to
pass primitives by value and use references only where appropriate,
since performance gains due to the use of the const qualifier are very
small and negligible in most cases.

	\Steve

--

Steve Grägert <steve@graegert.com>
Jabber    xmpp://graegerts@jabber.org
Internet  http://eth0.graegert.com, http://blog.graegert.com
-
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-04 18:38 ` Steve Graegert
  2007-04-05 12:05   ` Glynn Clements
@ 2007-04-08 14:45   ` Shriramana Sharma
  2007-04-13 17:51     ` Glynn Clements
  1 sibling, 1 reply; 11+ messages in thread
From: Shriramana Sharma @ 2007-04-08 14:45 UTC (permalink / raw)
  To: linux-c-programming

Steve Graegert wrote:

> I have seen many programs making use const reference parameters in
> order to inform the compiler that the parameter is read-only, and
> hence should be better optimized.

I thought the usage of const before & in function definitions was to 
prevent the value from being modified. I never knew there is an 
optimization aspect.

> Unfortunately, this intent is at odds with the C++ language
> definition. The const keyword says that the storage may not be
> modified through the given name. What it does not say is that the
> storage cannot be modified through some other name.

I observe that this is true for C too, not just C++. Anyway, how is it 
exactly "at odds" with the language definition?

[BTW gcc is intelligent enough to give me a compile-time warning:

const.c:7: warning: initialization discards qualifiers from pointer 
target type

when I write const int i = 2 ; int * iptr = & i ; and I don't even have 
to give -Wall !]

> you can only initialize them, const is basically ineffective a
> improving run-time performance. It does, however, catch errors in the
> programming process.

const is also useful for preventing a function writing to a variable 
passed to it as reference, which is what this thread was originally about.

Just for the record, are there any other uses for const?

Shriramana Sharma.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-05 13:02     ` Steve Graegert
@ 2007-04-08 15:17       ` Shriramana Sharma
  2007-04-13 17:23         ` Glynn Clements
  2007-04-14 13:15         ` Adam Dyga
  0 siblings, 2 replies; 11+ messages in thread
From: Shriramana Sharma @ 2007-04-08 15:17 UTC (permalink / raw)
  To: linux-c-programming

Steve Graegert wrote:

> If a programmer has chosen to pass a reference rather than a value,
> even if no reference is actually required, intentions to improve
> run-time performance come into mind.  It is much more intuitive to
> pass primitives by value and use references only where appropriate,
> since performance gains due to the use of the const qualifier are very
> small and negligible in most cases.

I am somewhat confused. As I see it, the usage of a const ref for 
passing a parameter by reference is to improve runtime performance, yes, 
but it is not through the "const" part of it. It is through the 
reference part of it, which avoids a copy of the parameter being 
constructed which can be costly with large classes or structs. The const 
part of it is only there to prevent the function from modifying the 
source data, whether intentionally or accidentally. There may be a 
side-effect of optimization, but at least to my understanding the intent 
of const here is making the source read-only. Is this understanding wrong?

I agree of course that in case of tiny tidbits of parameters like a few 
int-s, double-s or even std::string-s, there is not much meaning in 
using const ref-s, and it is more intuitive to pass these by value. It 
is only practically useful to pass big classes / struct-s by reference.

Shriramana Sharma.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-04 18:27 ` Glynn Clements
@ 2007-04-11 21:44   ` Adam Dyga
  0 siblings, 0 replies; 11+ messages in thread
From: Adam Dyga @ 2007-04-11 21:44 UTC (permalink / raw)
  To: linux-c-programming

On Wednesday, 4 April 2007 20:27, Glynn Clements wrote:

> Shriramana Sharma wrote:
> > Is providing an input to a function by constant reference more efficient
> > than passing it by value? In what way.
>
> Passing a reference doesn't copy the value. This can be significant if
> the value is large (i.e. a structure); for values which are no larger
> than a pointer, it is unlikely to make any difference.

For values which are not larger than a pointer, passing by reference can be 
even (slightly) slower, because the pointer must be dereferenced in the 
function in order to use the value:

void f1(const int v)
{
    printf("%d", v);
}

void f2(const int & v)
{
    printf("%d", v);
}


Compiled with -O2:

(gdb) disas f1
Dump of assembler code for function _Z2f1i:
0x08048460 <_Z2f1i+0>:  push   %ebp
0x08048461 <_Z2f1i+1>:  mov    %esp,%ebp
0x08048463 <_Z2f1i+3>:  sub    $0x10,%esp
0x08048466 <_Z2f1i+6>:  mov    0x8(%ebp),%eax
0x08048469 <_Z2f1i+9>:  push   %eax
0x0804846a <_Z2f1i+10>: push   $0x80485d4
0x0804846f <_Z2f1i+15>: call   0x8048358 <printf@plt>
0x08048474 <_Z2f1i+20>: leave
0x08048475 <_Z2f1i+21>: ret
End of assembler dump.
(gdb) disas f2
Dump of assembler code for function _Z2f2RKi:
0x08048480 <_Z2f2RKi+0>:        push   %ebp
0x08048481 <_Z2f2RKi+1>:        mov    %esp,%ebp
0x08048483 <_Z2f2RKi+3>:        sub    $0x10,%esp
0x08048486 <_Z2f2RKi+6>:        mov    0x8(%ebp),%eax
0x08048489 <_Z2f2RKi+9>:        mov    (%eax),%edx      //pointer dereference
0x0804848b <_Z2f2RKi+11>:       push   %edx
0x0804848c <_Z2f2RKi+12>:       push   $0x80485d4
0x08048491 <_Z2f2RKi+17>:       call   0x8048358 <printf@plt>
0x08048496 <_Z2f2RKi+22>:       leave
0x08048497 <_Z2f2RKi+23>:       ret
End of assembler dump.


Adam

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-08 15:17       ` Shriramana Sharma
@ 2007-04-13 17:23         ` Glynn Clements
  2007-04-14 13:15         ` Adam Dyga
  1 sibling, 0 replies; 11+ messages in thread
From: Glynn Clements @ 2007-04-13 17:23 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: linux-c-programming


Shriramana Sharma wrote:

> > If a programmer has chosen to pass a reference rather than a value,
> > even if no reference is actually required, intentions to improve
> > run-time performance come into mind.  It is much more intuitive to
> > pass primitives by value and use references only where appropriate,
> > since performance gains due to the use of the const qualifier are very
> > small and negligible in most cases.
> 
> I am somewhat confused. As I see it, the usage of a const ref for 
> passing a parameter by reference is to improve runtime performance, yes, 
> but it is not through the "const" part of it. It is through the 
> reference part of it, which avoids a copy of the parameter being 
> constructed which can be costly with large classes or structs. The const 
> part of it is only there to prevent the function from modifying the 
> source data, whether intentionally or accidentally. There may be a 
> side-effect of optimization, but at least to my understanding the intent 
> of const here is making the source read-only. Is this understanding wrong?

The const is primarily for correctness (ensuring that the callee
doesn't modify the data), but there may also be a performance gain.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-08 14:45   ` Shriramana Sharma
@ 2007-04-13 17:51     ` Glynn Clements
  0 siblings, 0 replies; 11+ messages in thread
From: Glynn Clements @ 2007-04-13 17:51 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: linux-c-programming


Shriramana Sharma wrote:

> > I have seen many programs making use const reference parameters in
> > order to inform the compiler that the parameter is read-only, and
> > hence should be better optimized.
> 
> I thought the usage of const before & in function definitions was to 
> prevent the value from being modified. I never knew there is an 
> optimization aspect.

There is, but it's usually secondary. Also, it's more likely that it
will enable optimisation in the caller than in the callee.

> > Unfortunately, this intent is at odds with the C++ language
> > definition. The const keyword says that the storage may not be
> > modified through the given name. What it does not say is that the
> > storage cannot be modified through some other name.
> 
> I observe that this is true for C too, not just C++. Anyway, how is it 
> exactly "at odds" with the language definition?

The fact that a const-qualified object may change eliminates many
possibilities for optimisation.

This is why the ANSI C standard includes certain rules regarding
"aliasing" (where several different expressions may actually refer to
the same region of memory).

These rules permit a compiler to assume that:

1. A value or array referenced by a pointer doesn't overlap a global
variable.

2. Primitive (non-struct/union) objects of different types don't
overlap.

E.g. consider the following code:

	int foo(int *p)
	{
		int x = globalvar++;
		int y = *p;
		return x * y;
	}

If it wishes, the compiler can swap the order in which x and y are
evaluated. Rule #1 above means that it doesn't have to consider the
possibility of being called as foo(&globalvar), where the globalvar++
would change the value of *p.

Without aliasing rules, many potential optimisations would have to be
foregone in case what appear to be distinct objects share the same
memory.

However, the aliasing rules state that the compiler cannot assume that
objects which are of the same type and which are both referenced
through pointers cannot overlap. So in the case of:

	int foo(int *p, int *q)
	{
		int x = (*p)++;
		int y = *q;
	}

the compiler cannot re-order the assignments because *p++ might modify
*q (if p == q).

If you write "clean" code, you don't need to worry about aliasing. 

Problems normally arise through the use of "type punning", where you
treat a specific area of memory as having two different types. E.g.

	union int_bytes {
		int i;
		unsigned char b[4];
	};

	...

	union int_bytes tmp;
	unsigned char lo_byte;

	tmp.i = 12345;
	lo_byte = tmp.b[0];

The above code may work fine when optimisation is disabled, but fail
when it is enabled.

This type of code is inevitably non-portable, as you are making
assumptions about the way in which specific types are stored in
memory.

This kind of "trick" is most common in low-level code which sacrifices
portability (and legibility) for performance. A good example is the
Linux kernel. This the main reason why it used to be quite common that
you had to use an older version of gcc to compile the kernel: because
newer versions optimised more aggressively, and thus were more likely
to break code which ignored the aliasing rules.

> [BTW gcc is intelligent enough to give me a compile-time warning:
> 
> const.c:7: warning: initialization discards qualifiers from pointer 
> target type
> 
> when I write const int i = 2 ; int * iptr = & i ; and I don't even have 
> to give -Wall !]
> 
> > you can only initialize them, const is basically ineffective a
> > improving run-time performance. It does, however, catch errors in the
> > programming process.
> 
> const is also useful for preventing a function writing to a variable 
> passed to it as reference, which is what this thread was originally about.
> 
> Just for the record, are there any other uses for const?

It enables certain optimisations, mostly in the caller. E.g. the code:

	y = x * 2;
	foo(&x);
	return y;

can be re-arranged as:

	foo(&x);
	y = x * 2;
	return y;

if foo is declared "void foo(const int *)" but not if it is declared
as "void foo(int *)", as the former is guaranteed not to modify x, but
the latter isn't.

Conversely, the "volatile" qualifier disables certain optimisations.

Neither "const" nor "volatile" were present in the original K&R C
language. They were added to the ANSI C standard specifically to deal
with issues related to optimisation.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: efficiency in passing a value to a function
  2007-04-08 15:17       ` Shriramana Sharma
  2007-04-13 17:23         ` Glynn Clements
@ 2007-04-14 13:15         ` Adam Dyga
  1 sibling, 0 replies; 11+ messages in thread
From: Adam Dyga @ 2007-04-14 13:15 UTC (permalink / raw)
  To: linux-c-programming

On Sunday, 8 April 2007 17:17, Shriramana Sharma wrote:

> I agree of course that in case of tiny tidbits of parameters like a few
> int-s, double-s or even std::string-s, there is not much meaning in
> using const ref-s, and it is more intuitive to pass these by value. It
> is only practically useful to pass big classes / struct-s by reference.

Well, std::string should be passed by const reference. Depending on the 
implementation, passing std::string by value may involve heap 
allocation/deallocation and memory copy operations which are quite costly.

Adam


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2007-04-14 13:15 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-04 17:13 efficiency in passing a value to a function Shriramana Sharma
2007-04-04 18:27 ` Glynn Clements
2007-04-11 21:44   ` Adam Dyga
2007-04-04 18:38 ` Steve Graegert
2007-04-05 12:05   ` Glynn Clements
2007-04-05 13:02     ` Steve Graegert
2007-04-08 15:17       ` Shriramana Sharma
2007-04-13 17:23         ` Glynn Clements
2007-04-14 13:15         ` Adam Dyga
2007-04-08 14:45   ` Shriramana Sharma
2007-04-13 17:51     ` Glynn Clements

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).