Why is const int faster than const int &?

I noticed this by accident once, and now decided to thoroughly test it.

So when I call the function:

#define Type int #define Prm const Type & Type testfunc1(Prm v1, Prm v2, Prm v3, Prm v4, Prm v5, Prm v6, Prm v7, Prm v8, Prm v9, Prm v10){ return (v1|v2|v3|v4|v5|v6|v7|v8|v9|v10); } 

100 million times:

  for(Type y = 0; y < 10000; y++){ for(Type x = 0; x < 10000; x++){ out |= testfunc1(x,y,x,x,y,y,x,y,x,y); } } 

With types int , const int and const int & I noticed that const int faster than const int & . (Note: im uses the return value to ensure that the function will not be optimized).

Why is that? I always thought that adding & would actually make it faster, but tests say otherwise. I know that for larger data types this will probably be a different result, I have not tested them, since I am quite confident in the results.

My tests:

 const int: 7.95s const int &: 10.2s 

Edit: I think this is really due to my architecture; I tested with a Sint64 type and the results were:

 const Sint64: 17.5s const Sint64 &: 16.2s 

Edit2: Or is it? Tested with type double (which is 64 bit?), And the results will puzzle me:

 const double: 11.28s const double &: 12.34s 

Edit3: updated the loop code to match my latest tests with 64-bit types.

+4
source share
3 answers

By putting & in the argument, you add more code to the program. Without & sequence:

  push values call Function pop values <- usually an update to stack pointer 

and in function:

  return sp[arg1] | sp[arg2] | etc <- value read direct from stack. 

Adding '&' does this:

  push address of value1 push address of value2 etc call Function pop values <- usually an update to stack pointer 

and in function:

  return_value = 0; address = sp[arg1] or return_value, [address] address = sp[arg2] or return_value, [address] etc return return_value 

So, as you can see, & adds a lot. So why use it? If you have a very large object, passing the pointer is more optimal than copying the object onto the stack.

+9
source

This result is highly system dependent. This indicates that on your particular system, copying the link value (which is most likely implemented as a pointer) is more expensive than copying the value of an integer. The most likely reason for this difference is that your integer needs 32 bits to represent, and your pointer / link representation requires 64 bits. EDIT . This is not to mention the cost of accessing integers: to obtain their values ​​will require additional indirectness. Since you only pass two elements, using caching hides the extra cost to a large extent, but the cost is there.

You are absolutely right in the larger types: although linking to, say, a large struct or vector<...> still requires only 64 bits (or any other size of this size on your system), no matter how many elements, that your structure has, or the number of elements of your vector<...> . The larger the structure, the higher the costs to convey it at cost, and therefore the savings that you understand by making it a link.

+7
source

Passing addresses instead of values ​​causes the addresses to go away (see shoot analysis or point analysis in your favorite compiler tutorial), which makes optimization difficult.

Yes, things like inline and connection time optimization can mitigate these problems.

+1
source

Source: https://habr.com/ru/post/1400619/


All Articles