.NET Forum / Languages / C# / December 2005
Another question about performance
|
|
Thread rating:  |
MuZZy - 23 Dec 2005 21:17 GMT Hi,
Consider this:
ArrayList al = new ArrayList(); FillList(al); /// NOW TWO SCENARIOS:
/// 1. for (int i = 0 ; i < al.Count ; i++) {..do whatever..}
/// 2. int iCount = al.Count; for (int i = 0 ; i < iCount ; i++) {..do whatever..}
Yes, as you have already figured out my question is about preffered scenario. I remember form the days of Delphi Pascal that you should preffer second scenario as in the first property Count will be requested on every loop.
Did anything change in C# and managed C++ or it's still proffered to use scenario 2?
Thank you MuZZy
Jon Skeet [C# MVP] - 23 Dec 2005 21:26 GMT > Consider this: > [quoted text clipped - 18 lines] > Did anything change in C# and managed C++ or it's still proffered to use > scenario 2? 1) The property will almost certainly be inlined anyway 2) The performance difference even if there is one is very, very unlikely to make any odds 3) The readability difference is much more significant, IMO 4) Do you actually need "i", or just the element? If it's the latter, consider using foreach instead.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
MuZZy - 23 Dec 2005 21:36 GMT >> Consider this: >> [quoted text clipped - 25 lines] > 4) Do you actually need "i", or just the element? If it's the latter, > consider using foreach instead. Thanks for your reply Jon!
Let's imagine that i need 'i' inside the loop, or that it's C++ so i can't use 'foreach'. Now, how does compiler inline property if there is no guarantee that it's not going to change inside the loop?
Jon Skeet [C# MVP] - 23 Dec 2005 21:42 GMT > Thanks for your reply Jon! > > Let's imagine that i need 'i' inside the loop, or that it's C++ so i > can't use 'foreach'. > Now, how does compiler inline property if there is no guarantee that > it's not going to change inside the loop? It inlines the property access so that there's no method call penalty - it doesn't shift the property access to before the start of the loop. It's the same as any other inlining.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Michael Nemtsev - 23 Dec 2005 21:57 GMT Hello Jon Skeet [C# MVP],
Whether don't using foreach give u slowing down? AFAIK, msdn posted about don't use foreach if u'd like to gain performance.
J> MuZZy <tnr@newsgroups.nospam> wrote:
>> /// 1. >> for (int i = 0 ; i < al.Count ; i++) [quoted text clipped - 6 lines] >> Did anything change in C# and managed C++ or it's still proffered to >> use scenario 2? J> 1) The property will almost certainly be inlined anyway J> 2) The performance difference even if there is one is very, very J> unlikely to make any odds J> 3) The readability difference is much more significant, IMO J> 4) Do you actually need "i", or just the element? If it's the latter, J> consider using foreach instead. --- WBR, Michael Nemtsev :: blog: http://spaces.msn.com/members/laflour
"At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsche
Jon Skeet [C# MVP] - 23 Dec 2005 22:03 GMT > Hello Jon Skeet [C# MVP], > > Whether don't using foreach give u slowing down? Not significantly in my experience - and I'm not interested in insignificant performance loss, pretty much by definition.
> AFAIK, msdn posted about don't use foreach if u'd like to gain performance. Well, that depends on which version of the framework you're using, and what type you're using. However, I wouldn't worry about it until I'd found it was decreasing the performance significantly, and that's never happened to me yet.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Michael Nemtsev - 23 Dec 2005 22:51 GMT Hello Jon Skeet [C# MVP],
But it should be taken into account. In my work I regularly meet the conditions when for example delay for 2 secons brakes functional requirements.
Itetating for 1,000,000 recors with for in 3-4 times faster than foreach.
But I'm agree that it's depends on type of product.
>> Whether don't using foreach give u slowing down? J> Not significantly in my experience - and I'm not interested in J> insignificant performance loss, pretty much by definition. J>
>> AFAIK, msdn posted about don't use foreach if u'd like to gain >> performance. J> Well, that depends on which version of the framework you're using, J> and what type you're using. However, I wouldn't worry about it until J> I'd found it was decreasing the performance significantly, and that's J> never happened to me yet. J> --- WBR, Michael Nemtsev :: blog: http://spaces.msn.com/members/laflour
"At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsch
Jon Skeet [C# MVP] - 23 Dec 2005 23:04 GMT > But it should be taken into account. In my work I regularly meet the conditions > when for example delay for 2 secons brakes functional requirements. It would be a very rare situation where using a different form of iteration would cost you even *nearly* that much. For instance, I can iterate through a 1,000,000 record ArrayList using foreach *a hundred times* in just over two seconds. Now, are you really doing that much iteration in the space of time in which two seconds breaks functional requirements?
> Itetating for 1,000,000 recors with for in 3-4 times faster than foreach. With what type? An ArrayList or an array? Big difference.
And what are you doing *inside* the loop? If you're not doing anything significant, you should ask yourself how often you actually iterate through a million records to do nothing with them. More often, in my experience, you do something significant within the loop which makes the actual iteration cost irrelevant.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Michael Nemtsev - 23 Dec 2005 23:48 GMT Hello Jon Skeet [C# MVP],
J> Michael Nemtsev <nemtsev@msn.com> wrote: J>
>> But it should be taken into account. In my work I regularly meet the >> conditions when for example delay for 2 secons brakes functional >> requirements. J> It would be a very rare situation where using a different form of J> iteration would cost you even *nearly* that much.
Indeed. Just a simple iterating 10,000,000 of int in int[] give u such difference with for and foreach
J> Now, are you really doing that much iteration in the space of time in which two seconds breaks functional J> requirements?
yep, but not just only using for :)
>> Itetating for 1,000,000 recors with for in 3-4 times faster than >> foreach. J> With what type? An ArrayList or an array? Big difference. let's take just int[] (not talking abt datasets ;) ), performance in that case differs in 2 times
J> And what are you doing *inside* the loop? If you're not doing J> anything significant, you should ask yourself how often you actually J> iterate through a million records to do nothing with them. More J> often, in my experience, you do something significant within the loop J> which makes the actual iteration cost irrelevant. Agree, but using *for* instead *foreach* in code not so hard (when even code navigation tools generate *for* template automatically) to win a bit more performance, if u r even only iterating and perform some financial calculations.
Jon, I'm not trying to argue abt *foreach* is bad and *for* rocks, I just wanna try to say, that using *for* is too simple . It's not a panacea. But if u r developing back-end/server side app, using *for* is more proper way
--- WBR, Michael Nemtsev :: blog: http://spaces.msn.com/members/laflour
"At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsche
Jon Skeet [C# MVP] - 24 Dec 2005 07:35 GMT > Hello Jon Skeet [C# MVP], > [quoted text clipped - 10 lines] > difference > with for and foreach Hmm. Not on my box - iterating through 10,000,000 ints using foreach takes 0.03 seconds. Here's my test code:
using System;
class Test { public static void Main(String [] args) { int[] x = new int[10000000]; int total=0; DateTime start = DateTime.Now; foreach (int y in x) { total += y; } Console.WriteLine (DateTime.Now-start); } }
What does that print on your box?
Don't forget to run it outside a debugger.
> J> Now, are you really doing that much iteration in the space of time in > which two seconds breaks functional > J> requirements? > > yep, but not just only using for :)
> >> Itetating for 1,000,000 recors with for in 3-4 times faster than > >> foreach. [quoted text clipped - 3 lines] > let's take just int[] (not talking abt datasets ;) ), performance in > that case differs in 2 times Not in my experiments. Here's another example:
using System;
class Test { public static void Main(String [] args) { int[] x = new int[10000000]; int total=0; DateTime start = DateTime.Now; for (int iteration = 0; iteration < 100; iteration++) { foreach (int y in x) { total += y; } } Console.WriteLine (DateTime.Now-start);
start = DateTime.Now; for (int iteration = 0; iteration < 100; iteration++) { for (int i=0; i < x.Length; i++) { total += x[i]; } } Console.WriteLine (DateTime.Now-start); } }
On my box, that prints: 00:00:02.1093750 00:00:02.0625000
In other words, not only can it do 100 times as many iterations as you claim to do before even reaching 2 seconds, but the speed difference is pretty insignificant. Now, the difference is more significant if you comment out the addition, but I think it's reasonable to assume you want to do *something* with the value inside the loop...
I don't understand how you're getting such different results, unless you're running them in the debugger. Even in the debugger I'm not seeing as much of a difference as you seem to be though.
What code did you use to test the difference?
> J> And what are you doing *inside* the loop? If you're not doing > J> anything significant, you should ask yourself how often you actually [quoted text clipped - 10 lines] > It's not a panacea. But if u r developing back-end/server side app, using > *for* is more proper way Only when you've found you've *actually* got a problem. It's easier to make a mistake with for than it is with foreach, and if you use foreach it's clear from reading the code that you're *only* interested in the values, and not in their positions. In other words, the code is simpler and conveys more correct information. *That* sounds like a the "more proper" way unless you *know* that you actually gain something significant from using a for loop.
Using the test code I've posted above, you'd have to be iterating through an array of 10,000,000 ints 5000 times in order to get a two second performance improvement. Now, unless you're actually doing very, very little work inside the loop, chances are that going through that much data is going to take so much time that 2 seconds becomes irrelevant.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Michael Nemtsev - 24 Dec 2005 08:37 GMT Hello Jon Skeet [C# MVP],
>> Indeed. Just a simple iterating 10,000,000 of int in int[] give u >> such >> difference >> with for and foreach J> Hmm. Not on my box - iterating through 10,000,000 ints using foreach J> takes 0.03 seconds. Here's my test code: J> J> What does that print on your box? J> Don't forget to run it outside a debugger.
The same result
>> J> Now, are you really doing that much iteration in the space of time >> in [quoted text clipped - 9 lines] >> let's take just int[] (not talking abt datasets ;) ), performance in >> that case differs in 2 times J> Not in my experiments. Here's another example: J> On my box, that prints: J> 00:00:02.1093750 J> 00:00:02.0625000
The same too
J> What code did you use to test the difference?
on big loops with rich logic inside
J> Only when you've found you've *actually* got a problem. It's easier J> to make a mistake with for than it is with foreach, and if you use J> foreach it's clear from reading the code that you're *only* J> interested in the values, and not in their positions. In other words, J> the code is simpler and conveys more correct information. *That* J> sounds like a the "more proper" way unless you *know* that you J> actually gain something significant from using a for loop.
Can't but agree too, but it's individual choice
J> Using the test code I've posted above, you'd have to be iterating J> through an array of 10,000,000 ints 5000 times in order to get a two J> second performance improvement. Now, unless you're actually doing J> very, very little work inside the loop, chances are that going J> through that much data is going to take so much time that 2 seconds J> becomes irrelevant.
My posts based on practical result, when I've seen the n-times improving performance changing foreach to for in nested loops. And it wasn't ArrayList. I totally agree that it's not important in must cases.
--- WBR, Michael Nemtsev :: blog: http://spaces.msn.com/members/laflour
"At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsche
Jon Skeet [C# MVP] - 24 Dec 2005 09:35 GMT <snip>
> J> What code did you use to test the difference? > > on big loops with rich logic inside And you saw a two second difference, using the same data, *just* changing from a for loop to a foreach loop? I hope you can see why I'm surprised, given the results we saw in my test code. The more complex the logic in the loop is, the less significance there will be in the iteration part.
> J> Only when you've found you've *actually* got a problem. It's easier > J> to make a mistake with for than it is with foreach, and if you use [quoted text clipped - 5 lines] > > Can't but agree too, but it's individual choice It's certainly an individual choice, but it should be an informed one. I would say that your blanket advice of "But if u r developing back- end/server side app, using *for* is more proper way" is mistaken, when in *most* cases the performance improvement isn't significant, but in *all* cases the foreach code is simpler and more readalbe.
> J> Using the test code I've posted above, you'd have to be iterating > J> through an array of 10,000,000 ints 5000 times in order to get a two [quoted text clipped - 7 lines] > > I totally agree that it's not important in must cases. I'd still be interested to hear more about the case you saw where it made a really significant improvement. I've just changed the test code to do more iterations over a smaller array. That shows a significant difference, but only when you get to the stage where you're iterating over a two element array. Even using a three element array doesn't show the problem. (Using 2.0 and compiling with optimisation on, this difference is reversed - array access at that stage takes longer than foreach.)
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Andreas Mueller - 23 Dec 2005 21:37 GMT > Hi, > [quoted text clipped - 23 lines] > Thank you > MuZZy It has changed, it is scenario (1) when you use the indexer to access the items in the ArrayList. By using al.Count there will be no runtime check :-) see http://tinyurl.com/3e9n3, part "Range Check Elimination"
Also, when you have an IEnumerable (which an ArrayList is) and the IEnumerable is *not* an System.Array, this is as good: foreach(OBJECT o in myList) { }
HTH, Andy
 Signature To email me directly, please remove the *NO*SPAM* parts below: *NO*SPAM*xmen40@*NO*SPAM*gmx.net
Jon Skeet [C# MVP] - 23 Dec 2005 21:37 GMT <snip>
> It has changed, it is scenario (1) when you use the indexer to access > the items in the ArrayList. By using al.Count there will be no runtime > check :-) > see http://tinyurl.com/3e9n3, part "Range Check Elimination" While I'm not saying it's a good idea to have a separate variable (see my other posts), are you sure range check elimination applies to ArrayLists as well as plain arrays? It doesn't explicitly say so in the page you linked to.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Andreas Mueller - 23 Dec 2005 23:59 GMT > <snip> > [quoted text clipped - 7 lines] > ArrayLists as well as plain arrays? It doesn't explicitly say so in the > page you linked to. No, that was a mistake from my side. It does not apply to ArrayList, just for System.Array.
Cheers, Andy
 Signature To email me directly, please remove the *NO*SPAM* parts below: *NO*SPAM*xmen40@*NO*SPAM*gmx.net
Robert Hooker - 27 Dec 2005 14:21 GMT Check out the excellent "Effective C#" by Bill Wagner - its written assuming .NET 1.1 (no doubt there will be a 2.0 shortly)
Item 11 (page 71) explains why your loop2 below is, in fact, the *slowest* way to write these loops in C# despite the fact it was the fastest way under C++ (doing it in .NET, you break the JITters ability to remove range checking for the loop). He also clearly explains why foreach is almost *always* the fastest method iterate over a collection.
Rob
> Hi, > [quoted text clipped - 23 lines] > Thank you > MuZZy
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|