Lieven Cardoen
Lieven Cardoen

Reputation: 25959

Is one of these for loops faster than the other?

for (var keyValue = 0; keyValue < dwhSessionDto.KeyValues.Count; keyValue++)
{...}


var count = dwhSessionDto.KeyValues.Count;
for (var keyValue = 0; keyValue < count; keyValue++)
{...}

I know there's a difference between the two, but is one of them faster than the other? I would think the second is faster.

Upvotes: 7

Views: 1620

Answers (7)

Jon Skeet
Jon Skeet

Reputation: 1500525

Yes, the first version is much slower. After all, I'm assuming you're dealing with types like this:

public class SlowCountProvider
{
    public int Count
    {
        get
        {
            Thread.Sleep(1000);
            return 10;
        }
    }
}

public class KeyValuesWithSlowCountProvider
{
    public SlowCountProvider KeyValues
    {
        get { return new SlowCountProvider(); }
    }
}

Here, your first loop will take ~10 seconds, whereas your second loop will take ~1 second.

Of course, you might argue that the assumption that you're using this code is unjustified - but my point is that the right answer will depend on the types involved, and the question doesn't state what those types are.

Now if you're actually dealing with a type where accessing KeyValues and Count is cheap (which is quite likely) I wouldn't expect there to be much difference. Mind you, I'd almost always prefer to use foreach where possible:

foreach (var pair in dwhSessionDto.KeyValues)
{
    // Use pair here
}

That way you never need the count. But then, you haven't said what you're trying to do inside the loop either. (Hint: to get more useful answers, provide more information.)

Upvotes: 38

mahju
mahju

Reputation: 1156

It is impossible to say without knowing the implementation of dwhSessionDto.KeyValues.Count and the loop body.

Assume a global variable bool foo = false; and then following implementations:

/* Loop body... */
{
    if(foo) Thread.Sleep(1000);
}

/* ... */
public int Count
{
    get
    {
        foo = !foo;            
        return 10;
    }
}
/* ... */

Now, the first loop will perform approximately twice as fast as the second ;D

However, assuming non-moronic implementation, the second one is indeed more likely to be faster.

Upvotes: 1

Andy
Andy

Reputation: 3743

The second version can be faster, sometimes. The point is that the condition is reevaluated after every iteration, so if e.g. the getter of "Count" actually counts the elements in an IEnumerable, or interogates a database /etc, this will slow things down.

So I'd say that if you dont affect the value of "Count" in the "for", the second version is safer.

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545588

See comments for reasons why this answer is wrong.

If there is a difference, it’s the other way round: Indeed, the first one might be faster. That’s because the compiler recognizes that you are iterating from 0 to the end of the array, and it can therefore elide bounds checks within the loop (i.e. when you access dwhSessionDTo.KeyValues[i]).

However, I believe the compiler only applies this optimization to arrays so there probably will be no difference here.

Upvotes: 1

Dean Chalk
Dean Chalk

Reputation: 20461

it depends how difficult it is to compute dwhSessionDto.KeyValues.Count if its just a pointer to an int then the speed of each version will be the same. However, if the Count value needs to be calculated, then it will be calculated every time, and therefore impede perfomance.

EDIT -- heres some code to demonstrate that the condition is always re-evaluated

public class Temp
{
    public int Count { get; set; }
}

static void Main(string[] args)
{
    var t = new Temp() {Count = 5};
    for (int i = 0; i < t.Count; i++)
    {
        Console.WriteLine(i);
        t.Count--;
    }
    Console.ReadLine();
}

The output is 0, 1, 2 - only !

Upvotes: 6

TalentTuner
TalentTuner

Reputation: 17556

There is no difference but why you think that thereis difference , can you please post your findings?

if you see the implementation of insert item in Dictionary using reflector

private void Insert(TKey key, TValue value, bool add)
{
int freeList;
if (key == null)
{
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (this.buckets == null)
{
    this.Initialize(0);
}
int num = this.comparer.GetHashCode(key) & 0x7fffffff;
int index = num % this.buckets.Length;
for (int i = this.buckets[index]; i >= 0; i = this.entries[i].next)
{
    if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
    {
        if (add)
        {
            ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
        }
        this.entries[i].value = value;
        this.version++;
        return;
    }
}
if (this.freeCount > 0)
{
    freeList = this.freeList;
    this.freeList = this.entries[freeList].next;
    this.freeCount--;
}
else
{
    if (this.count == this.entries.Length)
    {
        this.Resize();
        index = num % this.buckets.Length;
    }
    freeList = this.count;
    this.count++;
}
this.entries[freeList].hashCode = num;
this.entries[freeList].next = this.buckets[index];
this.entries[freeList].key = key;
this.entries[freeList].value = value;
this.buckets[index] = freeList;
this.version++;

}

Count is a internal member to this class which is incremented each item you insert an item into dictionary

so i beleive that there is no differenct at all.

Upvotes: 0

decyclone
decyclone

Reputation: 30830

No. There is no performance difference between these two loops. With JIT and Code Optimization, it does not make any difference.

Upvotes: 0

Related Questions