Friday, March 28, 2008

Are ForEach Loops Slower Then For Loops?

While reading some of Microsoft's patterns and practices material on optimizing .NET code I ran across an interesting comment. Microsoft recommends using for instead of foreach in performance sensitive loops.

To test I started out using the ArrayList on a bunch of strings. To get the best accuracy I P/Invoked GetTickCount . Here is what I found:

Collection SizeForeach Loop TicksFor Loop TicksPerformance Gain
5,000,0001099317.20%
10,000,00023417236.05%
20,000,00046835830.73%
50,000,000120292030.65%


Although the lower numbers were a bit sporadic the for loop did seem to function roughly 30% faster then the foreach. Lets look at what the foreach is doing. First lets look at a simple foreach loop:


foreach (string str in arr)
{
// Do Something
}


What is the foreach operator doing? It's calling GetEnumerator from arr and then calling MoveNext on each iteration.


IEnumerator enumerator = arr.GetEnumerator();
while (enumerator.MoveNext())
{
string str = (string)enumerator.Current;
// Do Something
}


MoveNext is called on each iteration of the loop. Using Lutz Roeder's .NET Reflector we can see what MoveNext is doing.


public bool MoveNext()
{
if (this.version != this.list._version)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
}
if (this.isArrayList)
{
if (this.index < (this.list._size - 1))
{
this.currentElement = this.list._items[++this.index];
return true;
}
this.currentElement = dummyObject;
this.index = this.list._size;
return false;
}
if (this.index < (this.list.Count - 1))
{
this.currentElement = this.list[++this.index];
return true;
}
this.index = this.list.Count;
this.currentElement = dummyObject;
return false;
}


We could step through this but lets look at only the lines that are run:



public bool MoveNext()
{
if (this.version != this.list._version) { }
if (this.isArrayList)
{
if (this.index < (this.list._size - 1))
{
this.currentElement = this.list._items[++this.index];
return true;
}
}
}


So it looks like our loop execution is being slowed down by some properties and conditional statements. This is insightful, but do we really care? Well if you are still reading this you might. If you are in the rare case that you need a insanely fast loop and you need precious milliseconds when looping millions of records you might want to replace your foreach loops with for loops. As for the sane rest of us I'm sure we can get a better return if we optimize the code within the loop.

Supplemental Links:
Loop Test Code

Save to del.icio.us Add to Technorati Add to dzone

Tuesday, March 25, 2008

Class Creation - To Create or Not To Create, That Is The Question.

It can be difficult to decide when to create a class. Most of the time it's clear when you need to create a class to perform a task but I've put together a list for those edge cases. Hopefully this will help you resolve your dilemma.

Reasons to create a class:


  • Model real-world objects
  • Model abstract objects
  • Reduce complexity
  • Isolate complexity
  • Hide implementation details
  • Limit effects of changes
  • Hide global data


Reasons not to create a class:

  • I want a class of my own
  • I want to name a class after myself
  • Tied of adding code to the same class
  • Because I want to


A large class or method is a telling sign that you need to refactor, but you need to elaborate on what your class or method is doing. Then try to break it out into logical or physical operations.

Also when you create your new class be sure to put it in it's own code file. I've found that maintaining a one to one relationship with your class and code files is critical to the maintainability of your code.

Save to del.icio.us Add to Technorati Add to dzone

Thursday, March 20, 2008

Multiple Boolean Variables Without all The Declarations

I need to have a bunch of boolean variables. Say I have a Car class that needs to indicate a bunch of features like air conditioning, leather seats, stereo, power windows, power seats or alarm system. I could declare the Car class like this:


public Car
{
public string Make;
public string Model;
public bool AirConditioning;
public bool LeatherSeats;
public bool Stereo;
public bool PowerWindows;
public bool PowerSeats;
public bool AlarmSystem;


Instead of declaring each variable individually you could use an enumeration flag. An enumeration flag uses bit wise operations on integer variables to represent multiple boolean variables. If you want to know more about bit wise operators take a look at the bit wise operation Wikipedia article.

Going back to our Car class we could declare the enumeration flag:


[Flags]
enum CarFeatures
{
AirConditioning=1,
LeatherSeats=2,
Stereo=4,
PowerWindows=8,
PowerSeats=16,
AlarmSystem=32
}


Remember each value needs to be a power of 2, because we are using them as bits and not as an integer. If you wanted more values then we have here you would continue with 64, 128, 256, 512, 1024, 2048, etc... Now we can declare our Car class's features as one variable:


public class Car
{
public string Make;
public string Model;
public CarFeatures Features;
}


To initialize our Car's features we can assign it as we would any other enumerator:


Car myCar = new Car();
myCar.Features = CarFeatures.Stereo;


If we want to assign it more then one value we need to use the or ("|") bit wise operator. It might help to think of the bit wise or ("|") as a merge or combine operator. Here is what it would look like in our Car example;


Car myCar = new Car();
myCar.Features = CarFeatures.Stereo | CarFeatures.AirConditioning;


Now that we have our features assigned to the Car how do we use them? Lets say we are looking for Cars that have air conditioning. Couldn't we use a standard comparison test? Example:


if (myCar.Features == CarFeatures.AirConditioning)
{
// This car has Air Conditioning
}


You would find cars with air conditioning, but the cars you would find wouldn't have any other features, including our previous car that had a stereo and air conditioning. In order to find cars that have air conditioning regardless of the other features we need to use the bit wise and ("&") operator. Lets rewrite our previous example to use the bit wise and ("&") operator:


if (myCar.Features & CarFeatures.AirConditioning == Car.Features.AirConditioning)
{
// This car has air conditioning and possibly other features as well.
}


The bit wise and ("&") operator extracts the CarFeatures.AirConditioning bit from myCar.Features. We need to the equals operator to actually test the bit we extracted. If the bit is "off" we will get 0. If the bit is "on" we will get the value of the bit in the CarFeatures.AirConditioning bit this would be 1. Here is a diagram of what is ocurring:


000101 (myCar.Features)
& 000001 (CarFeatures.AitConditioning)
--------
000001

000001 == 000001? True


Now you understand what going on. What about the length of the comparison? Well you can shorten it like this:


if (myCar.Features & Features.AirConditioning != 0)
{
// This car has air conditioning.
}


Both statements are correct. Just use them consistently.

Flag enumerations are great, but you should not go and replace all of your boolean values with enumeration flags. There are times when they can come in handy, but use them wisely.

Save to del.icio.us Add to Technorati Add to dzone