469,282 Members | 1,732 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,282 developers. It's quick & easy.

Foreach or For?

Hi,

I read somewhere that the new version (v1.1) has improved the
performance of 'foreach' over 'for'. Is that true? I did some
measurements and I still think for has an upperhand... ?

Phil

Nov 15 '05 #1
7 5357
Michael Mayer wrote:
I don't remember where I saw it, but I thought perhaps it was that
foreach was improved for arrays so it would act like a for loop. That
is, use simple indexing instead of MoveNext() and Current().
Even then I haven't been able to produce better results using foreach.
For out performs foreach in array accesses and array stores.
-Andre

I can't remember for the life of me where it was. Seems like it was one of
the microsoft blogs like blogs.gotdotnet.com, but google isn't showing
it. Too much work to search through my history list.

Wouldn't it be nice to have google search through all files in your
own history so you could re-find a page you saw a week ago? maybe
when I'm not so tired I'll think about this one some more...
mike

"Phil" <""nospam \"@ nospam> wrote in message
news:3f********@clarion.carno.net.au...
Hi,

I read somewhere that the new version (v1.1) has improved the
performance of 'foreach' over 'for'. Is that true? I did some
measurements and I still think for has an upperhand... ?

Phil



Nov 15 '05 #2
There are a number of faults in your test program.. in the for loop,
you're using a constant for the range.. you should use ints.Length
instead as the JIT compiler optimizes it further (and easily). Secondly,
use the profiling API instead for accurate results.

Try the following two tests:

using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
for(int j=0; j<n; j++)
{
tmp+=arr[j];
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}

And:
using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
foreach(int u in arr)
{
tmp+=u;
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}
Justify this.

-Andre
Austin Ehlers wrote:
I think you are noticing not the looping but the actual math being
done. Here's my code:

const ulong iterations=100000000;
DateTime dt;
uint[] ints={1,2,3,4,5,6,7,8,9,10};
uint len=10;
uint x=0;
ulong count=0;
dt=DateTime.Now;
ulong total=0;
while (count<iterations)
{
for (x=0;x<len;x++)
total+=ints[x];
count++;
}
TimeSpan ts1=DateTime.Now-dt;
count=0;
total=0;
dt=DateTime.Now;
while (count<iterations)
{
foreach (uint i in ints)
total+=i;
count++;
}
TimeSpan ts2=DateTime.Now-dt;

Console.WriteLine("For statement: {0} {1}ForEach statement: {2}",
ts1.ToString(), Environment.NewLine, ts2.ToString());
Console.ReadLine();

Austin Ehlers

On Mon, 28 Jul 2003 02:55:09 +1000, Andre <fo********@hotmail.com>
wrote:

Also, foreach incurs an array bounds check on every iteration.. I
suggest you change the count to 1000 and time again - you'll see a
noticeable difference. For me (i have a P4 2.4Ghz), a similar test
showed that For is atleast twice as fast as foreach.
-Andre

Austin Ehlers wrote:
On Sun, 27 Jul 2003 16:56:25 +1000, Phil <""nospam \"@ nospam> wrote:

Hi,

I read somewhere that the new version (v1.1) has improved the
performance of 'foreach' over 'for'. Is that true? I did some
measurements and I still think for has an upperhand... ?

Phil

I did a simple test. I cycled through an array of integers
{1,2,3,4,5,6,7,8,9,10} and added them to a total counter.
I did this 100 million times. On an Athlon XP 2400+, here are the
times:

for statement: 00:00:08.1093750
foreach statement: 00:00:08.1406250

As you can see, 4 hundredths of a second for 100 million times in
neglible. So, I'd say that in all but the most performance intensive
apps, foreach is equal to for in speed. (Don't forget, foreach is
readonly)

Austin Ehlers


Nov 15 '05 #3
There is another problem.. don't test the two loops in the same program.
I think the JIT optimizes it further by realizing that the same array is
being accessed, and so it probably utilizes hardware registers
(enresigeration or whatever the word is) or it rearranges code in a way
that the second access would be faster (by making sure data is already
available in cache).. so the second time you access the loop using
foreach, you get better results. If you switch the two loops, I think it
will show the same for the 'For' loop (not sure though - haven't
tested)... but if you try it out separately, you see a noticeable
difference.
-Andre

Andre wrote:
There are a number of faults in your test program.. in the for loop,
you're using a constant for the range.. you should use ints.Length
instead as the JIT compiler optimizes it further (and easily). Secondly,
use the profiling API instead for accurate results.

Try the following two tests:

using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
for(int j=0; j<n; j++)
{
tmp+=arr[j];
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}

And:
using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
foreach(int u in arr)
{
tmp+=u;
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}
Justify this.

-Andre
Austin Ehlers wrote:
I think you are noticing not the looping but the actual math being
done. Here's my code:

const ulong iterations=100000000;
DateTime dt;
uint[] ints={1,2,3,4,5,6,7,8,9,10};
uint len=10;
uint x=0;
ulong count=0;
dt=DateTime.Now;
ulong total=0;
while (count<iterations)
{
for (x=0;x<len;x++)
total+=ints[x];
count++;
}
TimeSpan ts1=DateTime.Now-dt;
count=0;
total=0;
dt=DateTime.Now;
while (count<iterations)
{
foreach (uint i in ints)
total+=i;
count++;
}
TimeSpan ts2=DateTime.Now-dt;

Console.WriteLine("For statement: {0} {1}ForEach statement: {2}",
ts1.ToString(), Environment.NewLine, ts2.ToString());
Console.ReadLine();

Austin Ehlers

On Mon, 28 Jul 2003 02:55:09 +1000, Andre <fo********@hotmail.com>
wrote:

Also, foreach incurs an array bounds check on every iteration.. I
suggest you change the count to 1000 and time again - you'll see a
noticeable difference. For me (i have a P4 2.4Ghz), a similar test
showed that For is atleast twice as fast as foreach.
-Andre

Austin Ehlers wrote:

On Sun, 27 Jul 2003 16:56:25 +1000, Phil <""nospam \"@ nospam> wrote:

> Hi,
>
> I read somewhere that the new version (v1.1) has improved the
> performance of 'foreach' over 'for'. Is that true? I did some
> measurements and I still think for has an upperhand... ?
>
> Phil
I did a simple test. I cycled through an array of integers
{1,2,3,4,5,6,7,8,9,10} and added them to a total counter.
I did this 100 million times. On an Athlon XP 2400+, here are the
times:

for statement: 00:00:08.1093750
foreach statement: 00:00:08.1406250

As you can see, 4 hundredths of a second for 100 million times in
neglible. So, I'd say that in all but the most performance intensive
apps, foreach is equal to for in speed. (Don't forget, foreach is
readonly)

Austin Ehlers


Nov 15 '05 #4
Using your code, compiled with as "csc for.cs" and "csc foreach.cs",
I get:

C:\>for.exe
Done in time(sec): 0.0318314199151009

C:\>foreach
Done in time(sec): 0.0212663900020813

I changed the j<n to j<arr.Length

Austin Ehlers

On Mon, 28 Jul 2003 13:15:06 +1000, Andre <fo********@hotmail.com>
wrote:
There are a number of faults in your test program.. in the for loop,
you're using a constant for the range.. you should use ints.Length
instead as the JIT compiler optimizes it further (and easily). Secondly,
use the profiling API instead for accurate results.

Try the following two tests:

using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
for(int j=0; j<n; j++)
{
tmp+=arr[j];
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}

And:
using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
foreach(int u in arr)
{
tmp+=u;
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}
Justify this.

-Andre
Austin Ehlers wrote:
I think you are noticing not the looping but the actual math being
done. Here's my code:

const ulong iterations=100000000;
DateTime dt;
uint[] ints={1,2,3,4,5,6,7,8,9,10};
uint len=10;
uint x=0;
ulong count=0;
dt=DateTime.Now;
ulong total=0;
while (count<iterations)
{
for (x=0;x<len;x++)
total+=ints[x];
count++;
}
TimeSpan ts1=DateTime.Now-dt;
count=0;
total=0;
dt=DateTime.Now;
while (count<iterations)
{
foreach (uint i in ints)
total+=i;
count++;
}
TimeSpan ts2=DateTime.Now-dt;

Console.WriteLine("For statement: {0} {1}ForEach statement: {2}",
ts1.ToString(), Environment.NewLine, ts2.ToString());
Console.ReadLine();

Austin Ehlers

On Mon, 28 Jul 2003 02:55:09 +1000, Andre <fo********@hotmail.com>
wrote:

Also, foreach incurs an array bounds check on every iteration.. I
suggest you change the count to 1000 and time again - you'll see a
noticeable difference. For me (i have a P4 2.4Ghz), a similar test
showed that For is atleast twice as fast as foreach.
-Andre

Austin Ehlers wrote:

On Sun, 27 Jul 2003 16:56:25 +1000, Phil <""nospam \"@ nospam> wrote:

>Hi,
>
>I read somewhere that the new version (v1.1) has improved the
>performance of 'foreach' over 'for'. Is that true? I did some
>measurements and I still think for has an upperhand... ?
>
>Phil

I did a simple test. I cycled through an array of integers
{1,2,3,4,5,6,7,8,9,10} and added them to a total counter.
I did this 100 million times. On an Athlon XP 2400+, here are the
times:

for statement: 00:00:08.1093750
foreach statement: 00:00:08.1406250

As you can see, 4 hundredths of a second for 100 million times in
neglible. So, I'd say that in all but the most performance intensive
apps, foreach is equal to for in speed. (Don't forget, foreach is
readonly)

Austin Ehlers


Nov 15 '05 #5
What machine do you have?

-Andre

Austin Ehlers wrote:
Using your code, compiled with as "csc for.cs" and "csc foreach.cs",
I get:

C:\>for.exe
Done in time(sec): 0.0318314199151009

C:\>foreach
Done in time(sec): 0.0212663900020813

I changed the j<n to j<arr.Length

Austin Ehlers

On Mon, 28 Jul 2003 13:15:06 +1000, Andre <fo********@hotmail.com>
wrote:

There are a number of faults in your test program.. in the for loop,
you're using a constant for the range.. you should use ints.Length
instead as the JIT compiler optimizes it further (and easily). Secondly,
use the profiling API instead for accurate results.

Try the following two tests:

using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
for(int j=0; j<n; j++)
{
tmp+=arr[j];
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}

And:
using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
foreach(int u in arr)
{
tmp+=u;
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}
Justify this.

-Andre
Austin Ehlers wrote:
I think you are noticing not the looping but the actual math being
done. Here's my code:

const ulong iterations=100000000;
DateTime dt;
uint[] ints={1,2,3,4,5,6,7,8,9,10};
uint len=10;
uint x=0;
ulong count=0;
dt=DateTime.Now;
ulong total=0;
while (count<iterations)
{
for (x=0;x<len;x++)
total+=ints[x];
count++;
}
TimeSpan ts1=DateTime.Now-dt;
count=0;
total=0;
dt=DateTime.Now;
while (count<iterations)
{
foreach (uint i in ints)
total+=i;
count++;
}
TimeSpan ts2=DateTime.Now-dt;

Console.WriteLine("For statement: {0} {1}ForEach statement: {2}",
ts1.ToString(), Environment.NewLine, ts2.ToString());
Console.ReadLine();

Austin Ehlers

On Mon, 28 Jul 2003 02:55:09 +1000, Andre <fo********@hotmail.com>
wrote:

Also, foreach incurs an array bounds check on every iteration.. I
suggest you change the count to 1000 and time again - you'll see a
noticeable difference. For me (i have a P4 2.4Ghz), a similar test
showed that For is atleast twice as fast as foreach.
-Andre

Austin Ehlers wrote:
>On Sun, 27 Jul 2003 16:56:25 +1000, Phil <""nospam \"@ nospam> wrote:
>
>
>
>
>>Hi,
>>
>>I read somewhere that the new version (v1.1) has improved the
>>performance of 'foreach' over 'for'. Is that true? I did some
>>measurements and I still think for has an upperhand... ?
>>
>>Phil
>
>I did a simple test. I cycled through an array of integers
>{1,2,3,4,5,6,7,8,9,10} and added them to a total counter.
>I did this 100 million times. On an Athlon XP 2400+, here are the
>times:
>
>for statement: 00:00:08.1093750
>foreach statement: 00:00:08.1406250
>
>As you can see, 4 hundredths of a second for 100 million times in
>neglible. So, I'd say that in all but the most performance intensive
>apps, foreach is equal to for in speed. (Don't forget, foreach is
>readonly)
>
>Austin Ehlers


Nov 15 '05 #6
I have a Pentium 4 2.4 Ghz, 256 MB RAM, .NET V1.1 here's what I get:

For loop:
Done in time(sec): 0.0169739450125644
Foreach loop:
Done in time(sec): 0.020767443906977
Can it be something to do with the hardware then?! I have no other
explanation.

-Andre

Austin Ehlers wrote:
An Athlon XP 2100+ (1.733GHz) overclocked to 1.911GHz (~2350+) on an
Asus A7N8X Deluxe with 512MB PC3200.

What numbers are you getting?

Austin Ehlers
On Tue, 29 Jul 2003 02:35:46 +1000, Andre <fo********@hotmail.com>
wrote:

What machine do you have?

-Andre

Austin Ehlers wrote:
Using your code, compiled with as "csc for.cs" and "csc foreach.cs",
I get:

C:\>for.exe
Done in time(sec): 0.0318314199151009

C:\>foreach
Done in time(sec): 0.0212663900020813

I changed the j<n to j<arr.Length

Austin Ehlers


<snip unneeded replies>


Nov 15 '05 #7
A couple of things. First, if you are sure of your array access code, you
can shut off bounds checking on each indexer access by marking the code as
unsafe. You can then obtain a pointer to the first element then move the
pointer since arrays are stored in contiguous memory space. This only works
for primitive types.

Also, as an FYI, you won't be able to change any values using the foreach
syntax since under the hood this loads up an enumerator with a copy of the
array.

"Andre" <fo********@hotmail.com> wrote in message
news:3F**************@hotmail.com...
There are a number of faults in your test program.. in the for loop,
you're using a constant for the range.. you should use ints.Length
instead as the JIT compiler optimizes it further (and easily). Secondly,
use the profiling API instead for accurate results.

Try the following two tests:

using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
for(int j=0; j<n; j++)
{
tmp+=arr[j];
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}

And:
using System;

class Class1
{
[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceCounter(ref long count);

[System.Runtime.InteropServices.DllImport ("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(ref long count);

[STAThread]
static void Main(string[] args)
{
long count = 0;
long count1 = 0;
long freq = 0;
double result = 0;
int tmp = 0;

int[] arr = new int[1000];

QueryPerformanceFrequency(ref freq);
QueryPerformanceCounter(ref count);
for (int i=0; i<20000; i++) {
foreach(int u in arr)
{
tmp+=u;
}
}
QueryPerformanceCounter(ref count1);

count = count1-count;
result = (double)(count)/(double)freq;

Console.WriteLine("Done in time(sec): {0}", result);
Console.ReadLine();
}
}
Justify this.

-Andre
Austin Ehlers wrote:
I think you are noticing not the looping but the actual math being
done. Here's my code:

const ulong iterations=100000000;
DateTime dt;
uint[] ints={1,2,3,4,5,6,7,8,9,10};
uint len=10;
uint x=0;
ulong count=0;
dt=DateTime.Now;
ulong total=0;
while (count<iterations)
{
for (x=0;x<len;x++)
total+=ints[x];
count++;
}
TimeSpan ts1=DateTime.Now-dt;
count=0;
total=0;
dt=DateTime.Now;
while (count<iterations)
{
foreach (uint i in ints)
total+=i;
count++;
}
TimeSpan ts2=DateTime.Now-dt;

Console.WriteLine("For statement: {0} {1}ForEach statement: {2}",
ts1.ToString(), Environment.NewLine, ts2.ToString());
Console.ReadLine();

Austin Ehlers

On Mon, 28 Jul 2003 02:55:09 +1000, Andre <fo********@hotmail.com>
wrote:

Also, foreach incurs an array bounds check on every iteration.. I
suggest you change the count to 1000 and time again - you'll see a
noticeable difference. For me (i have a P4 2.4Ghz), a similar test
showed that For is atleast twice as fast as foreach.
-Andre

Austin Ehlers wrote:

On Sun, 27 Jul 2003 16:56:25 +1000, Phil <""nospam \"@ nospam> wrote:

>Hi,
>
>I read somewhere that the new version (v1.1) has improved the
>performance of 'foreach' over 'for'. Is that true? I did some
>measurements and I still think for has an upperhand... ?
>
>Phil

I did a simple test. I cycled through an array of integers
{1,2,3,4,5,6,7,8,9,10} and added them to a total counter.
I did this 100 million times. On an Athlon XP 2400+, here are the
times:

for statement: 00:00:08.1093750
foreach statement: 00:00:08.1406250

As you can see, 4 hundredths of a second for 100 million times in
neglible. So, I'd say that in all but the most performance intensive
apps, foreach is equal to for in speed. (Don't forget, foreach is
readonly)

Austin Ehlers

Nov 15 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

8 posts views Thread by cody | last post: by
104 posts views Thread by cody | last post: by
27 posts views Thread by Tripper | last post: by
3 posts views Thread by Wiktor Zychla [C# MVP] | last post: by
7 posts views Thread by Osiris | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.