Today, when I use foreach loop to iterate a list <int>, I found that I became more familiar with performance problems, and I used to iterate an int arraylist, which I was a bit complacent. Benefiting from the benefits of generics, the C # compiler can use system. collections. generics. ienumerator <int> avoids a large number of boxing operations. collections. ienumerator. I started to think: Is this really the fastest way? After some research, this (foreach) is not the fastest way.
. NET 2.0 released some small nuggets, which makes it easier for us to write code. My favorite method is array and list <t>. Additional methods are added. These methods accept action <t>, converter <tinput, toutput> and predicate <t> are generic delegate. In fact, I am still fascinated by these things. The combination of these methods with anonymous methods and lambda expressions will play a significant role.
A special method of interest to me is list <t>. foreach (Action <t> ). I'm curious, is foreach calling faster or slower than a standard foreach-loop? Consider the following code:
[CSHARP]View plaincopyprint?
- Long sum (list <int> intlist)
- {
- Long result = 0;
- Foreach (int I in intlist)
- Result + = I;
- Return result;
- }
C # the compiler will generate pseudo code similar to the following for the above Code:
[CSHARP]View plaincopyprint?
- Long sum (list <int> intlist)
- {
- Long result = 0;
- List <t>. enumerator = intlist. getenumerator ();
- Try
- {
- While (enumerator. movenext ())
- {
- Int I = enumerator. Current;
- Result + = I;
- }
- }
- Finally
- {
- Enumerator. Dispose ();
- }
- Return result;
- }
In fact, the C # compiler generates two method calls for each iteration: ienumerator <t>. movenext () and ienumerator <t>. Current. List <t>. enumerator structure (implemented using ienumerator) allows the compiler to generateCallIl commands insteadCallvirtThis will improve performance a little. On the contrary, consider the following code:
[CSHARP]View plaincopyprint?
- Long sum (list <int> intlist)
- {
- Long result = 0;
- Intlist. foreach (delegate (int I) {result + = I ;});
- Result result;
- }
Or, the equivalent Lambda expression:
[CSHARP]View plaincopyprint?
- Long sum (list <int> intlist)
- {
- Long result = 0;
- Intlist. foreach (I => result + = I );
- Return result;
- }
Using list <t>. foreach only causes one method to be called in each iteration: No matter what action <t> delegate you provide. This will be called using the callvirt il command, but twoCallCommand (one movenext and one current) should be equal to oneCallvirtSlow command. So I expect that list <t>. foreach will be faster (than foreach ).
With these assumptions, I created a small console program, iterated A list <int> instance using different methods in the following 4, and summed up:
- Use for-loop iteration: For (INT I = 0; I <list <int>. Count; ++ I)
- Use for-loop, but do not call count: For (INT I = 0; I <num_items; ++ I)
- Use foreach-loop: foreach (int I in list <t>)
- Use List <int>. foreach for iteration: List <int>. foreach (delegate (int I) {result + = I ;})
First, optimization is not enabled in the test:
These results are unimaginable. Result: If Compiler optimization is not enabled, list <int>. foreach is faster than a for-loop! Foreach and for-loop are almost as fast. So if you compile your program without enabling optimization, list <int>. foreach is the fastest way.
Next, I turn on Compiler Optimization to get a more realistic result:
Looking at these numbers, the compiler is impressed with over 50% for-loop optimization. Foreach-loop also achieved an improvement of about 20%. List <int>. foreach does not get much optimization, but it should be noted that foreach is still much faster than foreach-loop.List <t>. foreach is faster than the standard foreach-loop..
Note that these tests run on a Dell think2's notebook with a CPU of Core Duo t2400 and 2 GB of memory. If you want to test some results by yourself, you can downloadForeachtest.zip (3.82kb ).
A picture is better than a thousand words. I generated a chart to show the speed difference between different iterations. The chart shows five different samples, from 10,000,000 to 50,000,000 iterations.
Compiler Optimization not started:
Enable Compiler Optimization:
Final point: although the foreach method is very fast in iterative list <t>, it is different when it comes to arrays. One-dimensional arrays do not have the foreach method, and foreach is much slower than foreach. The reason is that the compiler does not generate the ienumerator <t> code for the foreach iteration array. Using foreach to iterate the array, there is no way to call, but array. foreach will still call a delegate for each iteration (CallvirtCall ?).
Foreach vs list <t>. foreach