[ALL] Performance of foreach loop with arrays.

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[ALL] Performance of foreach loop with arrays.

sebb-2-2
Looking for feedback on C-style and foreach() loops when using arrays.
[This email does not consider collections; please start another thread
if you want to discuss that.]

TLDR; Always use foreach() with arrays unless you need access to the index.

==

There are two main ways to iterate over an array:

for(int i=0; i < array.length; i++ ) { // C-style
   doSomething(array[i]);
}

for(Object item : array) { // generic foreach
  doSomething(item);
}

The JVM has special instructions to load/store items from arrays;
different instructions are used for Objects and each primitive type;
these instructions only require the array start address and the index.

There have been suggestions that the for loop is less efficient
because it creates an iterator which needs to be garbage collected.

AFAICT in the case of *arrays* there is absolutely no need for the
compiler to create an iterator (or indeed any other temporary object)
in order to support the foreach() loop.

Experiments with javap confirm this.

IMO the only reason to prefer the C-style loop is where the index is
needed for something else in the loop.

Otherwise the foreach() loop seems much better to me:
- simpler to code and read
- cannot accidentally use the wrong index or wrong index comparison

Also the C-style loop evaluates the index each time through the loop;
one needs to code it as below to avoid this (the optimiser may do this
anyway):

int len = array.length; // take array length out of loop
for(int =0i; i < len; i++ ) { // C-style
   doSomething(array[i]);
}

This is even messier and more prone to error.

Note: javap does show an extra astore/aload instruction pair in the
test loop prior to calling doSomething() in the foreach() case. Those
appear to be superfluous and will presumably be optimised away at
runtime. A later compiler will likely fix this. In any case the
overhead of two local memory accesses is miniscule.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [ALL] Performance of foreach loop with arrays.

Stian Soiland-Reyes
On 16 May 2016 at 14:13, sebb <[hidden email]> wrote:
> Looking for feedback on C-style and foreach() loops when using arrays.
> [This email does not consider collections; please start another thread
> if you want to discuss that.]
>
> TLDR; Always use foreach() with arrays unless you need access to the index.

+1 - even if C-style happened to be faster (which I think you argue it
isn't), I would not think the majority of for-loops need that
micro-optimization.

Also note that in Java 8 (I know, I know.. we're still doing 6) you
can do lots of things in parallel with Arrays (including Streams):

https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html


--
Stian Soiland-Reyes
Apache Taverna (incubating), Apache Commons RDF (incubating)
http://orcid.org/0000-0001-9842-9718

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [ALL] Performance of foreach loop with arrays.

Eric Barnhill
In reply to this post by sebb-2-2
I have a related story. There is a class in commons-math 4.0 called
IntegerRange. Stylistically I much prefer Iterating over such a range than
C style loops and was ready to convert. However I found it many times
slower, at least in not terribly rigorous home micro-benchmarking.

Any good reason why this should be so?
On 16 May 2016 15:14, "sebb" <[hidden email]> wrote:

> Looking for feedback on C-style and foreach() loops when using arrays.
> [This email does not consider collections; please start another thread
> if you want to discuss that.]
>
> TLDR; Always use foreach() with arrays unless you need access to the index.
>
> ==
>
> There are two main ways to iterate over an array:
>
> for(int i=0; i < array.length; i++ ) { // C-style
>    doSomething(array[i]);
> }
>
> for(Object item : array) { // generic foreach
>   doSomething(item);
> }
>
> The JVM has special instructions to load/store items from arrays;
> different instructions are used for Objects and each primitive type;
> these instructions only require the array start address and the index.
>
> There have been suggestions that the for loop is less efficient
> because it creates an iterator which needs to be garbage collected.
>
> AFAICT in the case of *arrays* there is absolutely no need for the
> compiler to create an iterator (or indeed any other temporary object)
> in order to support the foreach() loop.
>
> Experiments with javap confirm this.
>
> IMO the only reason to prefer the C-style loop is where the index is
> needed for something else in the loop.
>
> Otherwise the foreach() loop seems much better to me:
> - simpler to code and read
> - cannot accidentally use the wrong index or wrong index comparison
>
> Also the C-style loop evaluates the index each time through the loop;
> one needs to code it as below to avoid this (the optimiser may do this
> anyway):
>
> int len = array.length; // take array length out of loop
> for(int =0i; i < len; i++ ) { // C-style
>    doSomething(array[i]);
> }
>
> This is even messier and more prone to error.
>
> Note: javap does show an extra astore/aload instruction pair in the
> test loop prior to calling doSomething() in the foreach() case. Those
> appear to be superfluous and will presumably be optimised away at
> runtime. A later compiler will likely fix this. In any case the
> overhead of two local memory accesses is miniscule.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [ALL] Performance of foreach loop with arrays.

Eric Barnhill
Sorry one further comment.

While I like iterators stylistically, in the design process I have
generally chosen to stick with C style loops.

This is because, often later in the design process, I decide I want access
to the index after all for some reason, and at point it is easier to call
the index, than redesign the iteration.

However I would be happy to stick with iterators as a matter of style in
apache commons.



On Tue, May 17, 2016 at 7:04 AM, Eric Barnhill <[hidden email]>
wrote:

> I have a related story. There is a class in commons-math 4.0 called
> IntegerRange. Stylistically I much prefer Iterating over such a range than
> C style loops and was ready to convert. However I found it many times
> slower, at least in not terribly rigorous home micro-benchmarking.
>
> Any good reason why this should be so?
> On 16 May 2016 15:14, "sebb" <[hidden email]> wrote:
>
>> Looking for feedback on C-style and foreach() loops when using arrays.
>> [This email does not consider collections; please start another thread
>> if you want to discuss that.]
>>
>> TLDR; Always use foreach() with arrays unless you need access to the
>> index.
>>
>> ==
>>
>> There are two main ways to iterate over an array:
>>
>> for(int i=0; i < array.length; i++ ) { // C-style
>>    doSomething(array[i]);
>> }
>>
>> for(Object item : array) { // generic foreach
>>   doSomething(item);
>> }
>>
>> The JVM has special instructions to load/store items from arrays;
>> different instructions are used for Objects and each primitive type;
>> these instructions only require the array start address and the index.
>>
>> There have been suggestions that the for loop is less efficient
>> because it creates an iterator which needs to be garbage collected.
>>
>> AFAICT in the case of *arrays* there is absolutely no need for the
>> compiler to create an iterator (or indeed any other temporary object)
>> in order to support the foreach() loop.
>>
>> Experiments with javap confirm this.
>>
>> IMO the only reason to prefer the C-style loop is where the index is
>> needed for something else in the loop.
>>
>> Otherwise the foreach() loop seems much better to me:
>> - simpler to code and read
>> - cannot accidentally use the wrong index or wrong index comparison
>>
>> Also the C-style loop evaluates the index each time through the loop;
>> one needs to code it as below to avoid this (the optimiser may do this
>> anyway):
>>
>> int len = array.length; // take array length out of loop
>> for(int =0i; i < len; i++ ) { // C-style
>>    doSomething(array[i]);
>> }
>>
>> This is even messier and more prone to error.
>>
>> Note: javap does show an extra astore/aload instruction pair in the
>> test loop prior to calling doSomething() in the foreach() case. Those
>> appear to be superfluous and will presumably be optimised away at
>> runtime. A later compiler will likely fix this. In any case the
>> overhead of two local memory accesses is miniscule.
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>
Reply | Threaded
Open this post in threaded view
|

Re: [ALL] Performance of foreach loop with arrays.

sebb-2-2
In reply to this post by Eric Barnhill
On 17 May 2016 at 06:04, Eric Barnhill <[hidden email]> wrote:
> I have a related story. There is a class in commons-math 4.0 called
> IntegerRange. Stylistically I much prefer Iterating over such a range than
> C style loops and was ready to convert. However I found it many times
> slower, at least in not terribly rigorous home micro-benchmarking.
>
> Any good reason why this should be so?

This is off-topic for the thread, which is about *arrays*.

Please start a new thread.

> On 16 May 2016 15:14, "sebb" <[hidden email]> wrote:
>
>> Looking for feedback on C-style and foreach() loops when using arrays.
>> [This email does not consider collections; please start another thread
>> if you want to discuss that.]
>>
>> TLDR; Always use foreach() with arrays unless you need access to the index.
>>
>> ==
>>
>> There are two main ways to iterate over an array:
>>
>> for(int i=0; i < array.length; i++ ) { // C-style
>>    doSomething(array[i]);
>> }
>>
>> for(Object item : array) { // generic foreach
>>   doSomething(item);
>> }
>>
>> The JVM has special instructions to load/store items from arrays;
>> different instructions are used for Objects and each primitive type;
>> these instructions only require the array start address and the index.
>>
>> There have been suggestions that the for loop is less efficient
>> because it creates an iterator which needs to be garbage collected.
>>
>> AFAICT in the case of *arrays* there is absolutely no need for the
>> compiler to create an iterator (or indeed any other temporary object)
>> in order to support the foreach() loop.
>>
>> Experiments with javap confirm this.
>>
>> IMO the only reason to prefer the C-style loop is where the index is
>> needed for something else in the loop.
>>
>> Otherwise the foreach() loop seems much better to me:
>> - simpler to code and read
>> - cannot accidentally use the wrong index or wrong index comparison
>>
>> Also the C-style loop evaluates the index each time through the loop;
>> one needs to code it as below to avoid this (the optimiser may do this
>> anyway):
>>
>> int len = array.length; // take array length out of loop
>> for(int =0i; i < len; i++ ) { // C-style
>>    doSomething(array[i]);
>> }
>>
>> This is even messier and more prone to error.
>>
>> Note: javap does show an extra astore/aload instruction pair in the
>> test loop prior to calling doSomething() in the foreach() case. Those
>> appear to be superfluous and will presumably be optimised away at
>> runtime. A later compiler will likely fix this. In any case the
>> overhead of two local memory accesses is miniscule.
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [ALL] Performance of foreach loop with arrays.

Benedikt Ritter-4
In reply to this post by sebb-2-2
sebb <[hidden email]> schrieb am Mo., 16. Mai 2016 um 15:14 Uhr:

> Looking for feedback on C-style and foreach() loops when using arrays.
> [This email does not consider collections; please start another thread
> if you want to discuss that.]
>
> TLDR; Always use foreach() with arrays unless you need access to the index.
>

+1


>
> ==
>
> There are two main ways to iterate over an array:
>
> for(int i=0; i < array.length; i++ ) { // C-style
>    doSomething(array[i]);
> }
>
> for(Object item : array) { // generic foreach
>   doSomething(item);
> }
>
> The JVM has special instructions to load/store items from arrays;
> different instructions are used for Objects and each primitive type;
> these instructions only require the array start address and the index.
>
> There have been suggestions that the for loop is less efficient
> because it creates an iterator which needs to be garbage collected.
>
> AFAICT in the case of *arrays* there is absolutely no need for the
> compiler to create an iterator (or indeed any other temporary object)
> in order to support the foreach() loop.
>
> Experiments with javap confirm this.
>
> IMO the only reason to prefer the C-style loop is where the index is
> needed for something else in the loop.
>
> Otherwise the foreach() loop seems much better to me:
> - simpler to code and read
> - cannot accidentally use the wrong index or wrong index comparison
>
> Also the C-style loop evaluates the index each time through the loop;
> one needs to code it as below to avoid this (the optimiser may do this
> anyway):
>
> int len = array.length; // take array length out of loop
> for(int =0i; i < len; i++ ) { // C-style
>    doSomething(array[i]);
> }
>
> This is even messier and more prone to error.
>
> Note: javap does show an extra astore/aload instruction pair in the
> test loop prior to calling doSomething() in the foreach() case. Those
> appear to be superfluous and will presumably be optimised away at
> runtime. A later compiler will likely fix this. In any case the
> overhead of two local memory accesses is miniscule.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>