473,978 Members | 30,060 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

foreach or List.ForEach

Which is the better way to go and why?

//trivial example
List<string> strings = GetStrings();
foreach (string s in strings)
{
// some operation;
}

strings.ForEach (
delegate(string s)
{
// some operation
}
);
Jan 19 '06
27 79989
Willy Denoyette [MVP] wrote:
| Sorry, yes, I misread which kind of ForEach you meant. The difference
| between copying it to an array and calling ForEach is that ForEach
| doesn't need the extra allocation. In other words, although using array
| copy / foreach is faster than using ForEach (if you copy it once and
| then iterate multiple times, at least), it's clearly more expensive in
| terms of memory.

True, there is the memory cost. isn't making "informed and sound design
tradeoffs" the beauty of software design?
:)
| Interesting. I've been running with .NET 1.1. I'll try it later with
| .NET 2.0 and see if that makes a difference.

Hmmmm... generics and anon delegates on v1.1???
Okay, I clearly need to get more sleep...
| Well, there's significantly less codependence in the new version, so
| I'm not entirely surprised. It's a more realistic test in various ways.

Yep, but there is more than the performance drop. The same test runs
correctly on Intel P4 and Mobile HW, but shows this pattern on 32/64 bit AMD
and Intel.


Ah, interesting. Are you investigating much further, or just shipping
it off to MS? It sounds like something they ought to know about, and
it's already a pretty short bit of code to reproduce the problem...

Jon

Jan 20 '06 #21

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:11******** **************@ g47g2000cwa.goo glegroups.com.. .
| Willy Denoyette [MVP] wrote:
| > | Sorry, yes, I misread which kind of ForEach you meant. The difference
| > | between copying it to an array and calling ForEach is that ForEach
| > | doesn't need the extra allocation. In other words, although using
array
| > | copy / foreach is faster than using ForEach (if you copy it once and
| > | then iterate multiple times, at least), it's clearly more expensive in
| > | terms of memory.
| >
| > True, there is the memory cost. isn't making "informed and sound design
| > tradeoffs" the beauty of software design?
|
| :)
|
| > | Interesting. I've been running with .NET 1.1. I'll try it later with
| > | .NET 2.0 and see if that makes a difference.
| >
| > Hmmmm... generics and anon delegates on v1.1???
|
| Okay, I clearly need to get more sleep...
|
| > | Well, there's significantly less codependence in the new version, so
| > | I'm not entirely surprised. It's a more realistic test in various
ways.
| >
| > Yep, but there is more than the performance drop. The same test runs
| > correctly on Intel P4 and Mobile HW, but shows this pattern on 32/64 bit
AMD
| > and Intel.
|
| Ah, interesting. Are you investigating much further, or just shipping
| it off to MS? It sounds like something they ought to know about, and
| it's already a pretty short bit of code to reproduce the problem...
|

Yes, it's a short bit of code, but it drives a complex machinery. Actually
(well say next Monday) a guy much smarter than me, will investigate this
further to see whether it's purely an HW issue or not. I'll see what I can
do to keep you informed if you want to.

Willy.
Jan 20 '06 #22
Willy Denoyette [MVP] <wi************ *@telenet.be> wrote:

<snip>
| Ah, interesting. Are you investigating much further, or just shipping
| it off to MS? It sounds like something they ought to know about, and
| it's already a pretty short bit of code to reproduce the problem...

Yes, it's a short bit of code, but it drives a complex machinery. Actually
(well say next Monday) a guy much smarter than me, will investigate this
further to see whether it's purely an HW issue or not. I'll see what I can
do to keep you informed if you want to.


Yes, please do :)

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jan 20 '06 #23

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
| Willy Denoyette [MVP] <wi************ *@telenet.be> wrote:
|
| <snip>
|
| > | Ah, interesting. Are you investigating much further, or just shipping
| > | it off to MS? It sounds like something they ought to know about, and
| > | it's already a pretty short bit of code to reproduce the problem...
| >
| > Yes, it's a short bit of code, but it drives a complex machinery.
Actually
| > (well say next Monday) a guy much smarter than me, will investigate this
| > further to see whether it's purely an HW issue or not. I'll see what I
can
| > do to keep you informed if you want to.
|
| Yes, please do :)
|
| --
| Jon Skeet - <sk***@pobox.co m>
| http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
| If replying to the group, please do not mail me too

Ok, we finished a code analysis on different HW, and it turns out (in short)
that the issue relates to the size of the L2 cache the memory systems
hierarchy and the memory model.
Processors with 512KB or less do have the issue I mentioned above,
processors with 1MB and 2MB caches do not have the issue with the code as
posted, but they show the same behavior with larger List's, and in
real-world applications.
If you change the code line
List<string> list = new List<string>();
into:
List<string> list = new List<string>(Si ze);
and run the code, you'll see consistent behavior. The reason is that the
former code line creates a List with 132076 entries (null initialized) while
the latter creates a List with 100000 entries, that is, 13076 * 4 and 100000
* 4 bytes respectively. This means that in the first case, the L2 cache has
no more room left after the List is initialized and 'filled', in the latter
case the cache has ~100000 bytes 'free', which is enough to load the
delegates IL and compile it when the second test starts executing.
Willy.
Jan 24 '06 #24
Willy Denoyette [MVP] wrote:

<snip>
Ok, we finished a code analysis on different HW, and it turns out (in short)
that the issue relates to the size of the L2 cache the memory systems
hierarchy and the memory model.
Processors with 512KB or less do have the issue I mentioned above,
processors with 1MB and 2MB caches do not have the issue with the code as
posted, but they show the same behavior with larger List's, and in
real-world applications.
If you change the code line
List<string> list = new List<string>();
into:
List<string> list = new List<string>(Si ze);
and run the code, you'll see consistent behavior. The reason is that the
former code line creates a List with 132076 entries (null initialized) while
the latter creates a List with 100000 entries, that is, 13076 * 4 and 100000
* 4 bytes respectively. This means that in the first case, the L2 cache has
no more room left after the List is initialized and 'filled', in the latter
case the cache has ~100000 bytes 'free', which is enough to load the
delegates IL and compile it when the second test starts executing.


Wow. Interesting stuff. Doesn't explain the profiler dying, of course
:)

Of course, in the real world the cost of the iteration is usually not
going to be the limiting factor, but it's fascinating to see the
difference this can make.

Jon

Jan 24 '06 #25

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:11******** *************@g 47g2000cwa.goog legroups.com...
| Willy Denoyette [MVP] wrote:
|
| <snip>
|
| > Ok, we finished a code analysis on different HW, and it turns out (in
short)
| > that the issue relates to the size of the L2 cache the memory systems
| > hierarchy and the memory model.
| > Processors with 512KB or less do have the issue I mentioned above,
| > processors with 1MB and 2MB caches do not have the issue with the code
as
| > posted, but they show the same behavior with larger List's, and in
| > real-world applications.
| > If you change the code line
| > List<string> list = new List<string>();
| > into:
| > List<string> list = new List<string>(Si ze);
| > and run the code, you'll see consistent behavior. The reason is that the
| > former code line creates a List with 132076 entries (null initialized)
while
| > the latter creates a List with 100000 entries, that is, 13076 * 4 and
100000
| > * 4 bytes respectively. This means that in the first case, the L2 cache
has
| > no more room left after the List is initialized and 'filled', in the
latter
| > case the cache has ~100000 bytes 'free', which is enough to load the
| > delegates IL and compile it when the second test starts executing.
|
| Wow. Interesting stuff. Doesn't explain the profiler dying, of course
| :)
|
| Of course, in the real world the cost of the iteration is usually not
| going to be the limiting factor, but it's fascinating to see the
| difference this can make.
|
| Jon
|

The VS profiler dying is still under investigation (it's intermittent), all
we know is that it's timing related. People in our joint MS competence
center are further investigating this.
The in-house profiler issue was a bug in the profiler code which incorrectly
handled the anon delegate target creation, something that gets done when the
List.ForEach method runs for the first time (so not at method JIT time).
And that's also the biggest difference between both:

list.ForEach (delegate(strin g s) { sum += s.Length; });
and:
list.ForEach (action);

In the former case the delegate target is loaded from the IL and JIT
compiled when ForEach executes for the first time (quite interesting to
follow the code path, really). In the latter case the target is built before
'ForEach' runs (but also after the method gets JIT compiled). The resulting
code (after the first iteration) is exactly the same for both cases, BUT the
former is quite disturbing the cache (L1 and L2) in this particular test
(where the cache already contains most of the data to be iterated over).

Willy.



Jan 24 '06 #26
>People in our joint MS competence center are further investigating this.
You work for MS?

--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ www.lulu.com/owc
Forth-coming VSTO.NET - Wrox/Wiley 2006
-------------------------------------------------------

"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message
news:ed******** ******@TK2MSFTN GP09.phx.gbl...

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:11******** *************@g 47g2000cwa.goog legroups.com...
| Willy Denoyette [MVP] wrote:
|
| <snip>
|
| > Ok, we finished a code analysis on different HW, and it turns out (in
short)
| > that the issue relates to the size of the L2 cache the memory systems
| > hierarchy and the memory model.
| > Processors with 512KB or less do have the issue I mentioned above,
| > processors with 1MB and 2MB caches do not have the issue with the code
as
| > posted, but they show the same behavior with larger List's, and in
| > real-world applications.
| > If you change the code line
| > List<string> list = new List<string>();
| > into:
| > List<string> list = new List<string>(Si ze);
| > and run the code, you'll see consistent behavior. The reason is that the | > former code line creates a List with 132076 entries (null initialized)
while
| > the latter creates a List with 100000 entries, that is, 13076 * 4 and
100000
| > * 4 bytes respectively. This means that in the first case, the L2 cache has
| > no more room left after the List is initialized and 'filled', in the
latter
| > case the cache has ~100000 bytes 'free', which is enough to load the
| > delegates IL and compile it when the second test starts executing.
|
| Wow. Interesting stuff. Doesn't explain the profiler dying, of course
| :)
|
| Of course, in the real world the cost of the iteration is usually not
| going to be the limiting factor, but it's fascinating to see the
| difference this can make.
|
| Jon
|

The VS profiler dying is still under investigation (it's intermittent), all we know is that it's timing related. People in our joint MS competence
center are further investigating this.
The in-house profiler issue was a bug in the profiler code which incorrectly handled the anon delegate target creation, something that gets done when the List.ForEach method runs for the first time (so not at method JIT time).
And that's also the biggest difference between both:

list.ForEach (delegate(strin g s) { sum += s.Length; });
and:
list.ForEach (action);

In the former case the delegate target is loaded from the IL and JIT
compiled when ForEach executes for the first time (quite interesting to
follow the code path, really). In the latter case the target is built before 'ForEach' runs (but also after the method gets JIT compiled). The resulting code (after the first iteration) is exactly the same for both cases, BUT the former is quite disturbing the cache (L1 and L2) in this particular test
(where the cache already contains most of the data to be iterated over).

Willy.


Jan 24 '06 #27
Alvin,

No, I don't. Major IHV's (and Universities) and large software companies
(MS, Oracle, SAP, etc..) have established all sort of 'joint' programs. A
'joint competence' program is one where both companies share their
knowledge, a 'joint R&D' program is one where they share research and
development efforts.

Willy.

"Alvin Bruney - ASP.NET MVP" <www.lulu.com/owc> wrote in message
news:u0******** ******@TK2MSFTN GP14.phx.gbl...
| >People in our joint MS competence center are further investigating this.
| You work for MS?
|
| --
| Regards,
| Alvin Bruney [MVP ASP.NET]
|
| [Shameless Author plug]
| The Microsoft Office Web Components Black Book with .NET
| Now Available @ www.lulu.com/owc
| Forth-coming VSTO.NET - Wrox/Wiley 2006
| -------------------------------------------------------
|
|
|
| "Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message
| news:ed******** ******@TK2MSFTN GP09.phx.gbl...
| >
| > "Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
| > news:11******** *************@g 47g2000cwa.goog legroups.com...
| > | Willy Denoyette [MVP] wrote:
| > |
| > | <snip>
| > |
| > | > Ok, we finished a code analysis on different HW, and it turns out
(in
| > short)
| > | > that the issue relates to the size of the L2 cache the memory
systems
| > | > hierarchy and the memory model.
| > | > Processors with 512KB or less do have the issue I mentioned above,
| > | > processors with 1MB and 2MB caches do not have the issue with the
code
| > as
| > | > posted, but they show the same behavior with larger List's, and in
| > | > real-world applications.
| > | > If you change the code line
| > | > List<string> list = new List<string>();
| > | > into:
| > | > List<string> list = new List<string>(Si ze);
| > | > and run the code, you'll see consistent behavior. The reason is that
| the
| > | > former code line creates a List with 132076 entries (null
initialized)
| > while
| > | > the latter creates a List with 100000 entries, that is, 13076 * 4
and
| > 100000
| > | > * 4 bytes respectively. This means that in the first case, the L2
| cache
| > has
| > | > no more room left after the List is initialized and 'filled', in the
| > latter
| > | > case the cache has ~100000 bytes 'free', which is enough to load the
| > | > delegates IL and compile it when the second test starts executing.
| > |
| > | Wow. Interesting stuff. Doesn't explain the profiler dying, of course
| > | :)
| > |
| > | Of course, in the real world the cost of the iteration is usually not
| > | going to be the limiting factor, but it's fascinating to see the
| > | difference this can make.
| > |
| > | Jon
| > |
| >
| > The VS profiler dying is still under investigation (it's intermittent),
| all
| > we know is that it's timing related. People in our joint MS competence
| > center are further investigating this.
| > The in-house profiler issue was a bug in the profiler code which
| incorrectly
| > handled the anon delegate target creation, something that gets done when
| the
| > List.ForEach method runs for the first time (so not at method JIT time).
| > And that's also the biggest difference between both:
| >
| > list.ForEach (delegate(strin g s) { sum += s.Length; });
| > and:
| > list.ForEach (action);
| >
| > In the former case the delegate target is loaded from the IL and JIT
| > compiled when ForEach executes for the first time (quite interesting to
| > follow the code path, really). In the latter case the target is built
| before
| > 'ForEach' runs (but also after the method gets JIT compiled). The
| resulting
| > code (after the first iteration) is exactly the same for both cases, BUT
| the
| > former is quite disturbing the cache (L1 and L2) in this particular test
| > (where the cache already contains most of the data to be iterated over).
| >
| > Willy.
| >
| >
| >
| >
| >
| >
| >
|
|
Jan 25 '06 #28

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
7975
by: Jeffrey Silverman | last post by:
Hi, all. I have a linked list. I need an algorithm to create a tree structure from that list. Basically, I want to turn this: $list = array( array( 'id' => 'A', 'parent_id' => null, 'value' => 'aaa') , array( 'id' => 'B', 'parent_id' => 'A', 'value' => 'bbb') , array( 'id' => 'C', 'parent_id' => 'B', 'value' => 'ccc') , array( 'id' => 'D', 'parent_id' => 'A', 'value' => 'ddd')
32
4224
by: James Curran | last post by:
I'd like to make the following proposal for a new feature for the C# language. I have no connection with the C# team at Microsoft. I'm posting it here to gather input to refine it, in an "open Source" manner, and in an attempt to build a ground-swell of support to convince the folks at Microsoft to add it. Proposal: "first:" "last:" sections in a "foreach" block The problem: The foreach statement allows iterating over all the...
13
2025
by: cody | last post by:
foreach does implicitly cast every object in the collection to the specified taget type without warning. Without generics this behaviour had the advantage of less typing for us since casting was neccessary in nearly every collection. But with generics I consider this feature of foreach as dangerous. Casting is now almost always unwanted. interface IFoo{} class Foo:IFoo{} class FooBar:IFoo{}
9
2818
by: garyusenet | last post by:
I'm a bit confused about the differences of these two commands (what is the right word for commands here?) when used to enumerate the contents of an array. The below example uses both foreach and for to enumerate the contents of the array. Also as well as explaining the differences could you explain why the foreach messagebox isn't working below. Many TIA.
7
4060
by: =?Utf-8?B?RXZhbiBSZXlub2xkcw==?= | last post by:
I am a C++ programmer and have been learning C#. I have constructed a List<> and I want to iterate over it, altering each string in the list. In C++, I'd just create an iterator and walk the list, so I was looking for something similar in C#. I looked at foreach, List.ForEach, and IEnumerator. The problem is that all of them seem to return readonly pointers to the items in the List. Therefore I can't alter the list. So I'm using a for...
3
2207
by: =?Utf-8?B?YW1pcg==?= | last post by:
Hi, I have a Generic Object that has a private List field item. I populate the List in a different function I use a FOREACH LOOP with a FindAll function to get all items that have a certain match for data in the list and do something to it. The problem is that it repeats for all data items in the list and not
4
2599
by: Peter Morris | last post by:
I am not sure what you are asking. You seem to be asking how to implement a plain IEnumerable on a composite structure, but then your example shows a flat structure using "yield". Your subject makes me infer that you think foreach is enirely useless for composite structures. I will address the subject text, because that makes the most sense to me :-) Take the following class public class MyTreeNode : IEnumerable<MyTreeNode> {
0
10358
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
11425
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
11593
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10087
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
8465
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7620
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
6424
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
5162
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4742
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.