nested variables in loops - inefficient?

G

Guest

Using local declarations within a block often makes code more readable, but
is it less efficient? eg...

void P() {
while (...) {
int i = ...;
bool b = ...;
....
}
}

At first sight this looks inefficient, because i and b are being allocated
each time around the loop. But I wonder if that is really the case. I have
heard that when procedure P is placed on the stack, that *all* variables
within P, including those within a nested scope, are also allocated. ie. in
the above example, i and b would be allocated only once, at the start of the
procedure. However, I am not sure whether this is the true.

What if the the variable is nested within a conditional - is it still always
allocated at the start? eg...

while (...) {
if (...) {
int i = ...;
bool b = ...;
....
}
}


Any experts here who can ease my mind about the possible ineffiency of
nested variables?

A bit of background - I'm writing a real time application, with several
complex loops processing data which is being received at a high rate, so I
keep coming across this dilemna.

TIA,

Javaman
 
C

cody

No matter *where* the variables are located in the method: they all are
allocated only *once*.
But if you assign a value to them, e.g. int i=0; the assignment takes place
everytime this line of code is executed.
 
G

Guest

There answer to your efficiency question is that it depends. In a release
build where the compiler optimizes your code it will defintely move the int
outside the scope of the loop. For value types it really doesn't matter
because they'll be on the stack anyway. For reference types however each
time through the loop would cause the object to be release and therefore
potentially GC'ed while a new one is created. Thus I wouldn't do this sort
of thing for strings.

The more important question however is the initialization of that var.
Given your code do you expect the local to be inited each time through the
loop? If so then the assignment must happen during each iteration even if
the object creation happens only once.

By moving the var outside the loop you are also impacting the visibility
scope of the var. You won't be able to declare another "i" in this function
if it is moved outside the loop. However if it remains in the loop then you
can reuse "i" in other loops.

Compilers are really good at optimizing simple cases like this one. The
compiler will move any code that is loop invariant outside the scope of the
loop. Therefore I wouldn't worry about the general case you mentioned unless
you're dealing with reference types.

Personally I always put local vars outside the loop but this is really a
holdover from my days of writing real-time compilers in C++. It's not as
readable but it feels "faster" to me.

Michael Taylor - 9/19/05
 
C

Cool Guy

Javaman59 said:
Using local declarations within a block often makes code more readable, but
is it less efficient? eg...

void P() {
while (...) {
int i = ...;
bool b = ...;
....
}
}

In the following, P() And Q() compile down to the exact same IL for me (and
optimization is *off*). You can try it yourself with ILDASM.

using System;

class Test
{
static void Main() {
P();
Q();
}

static void P() {
while (true) {
int i = Console.Read();
bool b = i == 5;
Console.WriteLine(i);
Console.WriteLine(b);
}
}

static void Q() {
int i;
bool b;
while (true) {
i = Console.Read();
b = i == 5;
Console.WriteLine(i);
Console.WriteLine(b);
}
}
}
 
G

Guest

Thanks! Your reply came in while I was writing my own response to the other
two.

Thanks for writing that bit of code. I think that settles it. Smart to use "
int i = Console.Read(); bool b = i == 5;" to ensure that the compiler
doesn't optimise the expressions!

Regards,

Javaman.
 
G

Guest

Thanks, very much.
while (...) {
int i = ...;
bool b = ...;
....
}

Both of you pointed out that I needn't be concerned about the allocation of
the variables - that will happen once only, no matter where they are in the
method. The right of the assignment statement will be executed each time
round the loop, obviously, and in my case it needs to be, as the value of the
expression changes each time.

So, I don't really need to declare the variables outside the loop for the
sake of efficiency (it makes no difference), but, still, my instincts are the
same as Michael's...

Somehow, the declaration outside the loop feels right to me. Perhaps it is
actually clearer, as it shows what is changing with each iteration.

Thanks again,

Javaman
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

TaylorMichaelL said:
There answer to your efficiency question is that it depends. In a release
build where the compiler optimizes your code it will defintely move the
int
outside the scope of the loop. For value types it really doesn't matter
because they'll be on the stack anyway. For reference types however each
time through the loop would cause the object to be release and therefore
potentially GC'ed while a new one is created. Thus I wouldn't do this
sort
of thing for strings.

Well usually you use that construction to hold a reference to an object
already created and that is currently being referenced by another mean, in
which case you do not have that problem.
Neither you have more choises if what is created is the return of a method
that create a new instance. instance that you should need to use in the
loop.
The more important question however is the initialization of that var.
Given your code do you expect the local to be inited each time through the
loop? If so then the assignment must happen during each iteration even if
the object creation happens only once.

With values types it shoudl not matter, I'm not very familiar with the IL
code, but I bet you that the space in the stack is reserved only once. The
assignment will happen in each iteration, and that is why you have it inside
the loop in the first place. Ideally it should get a new value in each
iteration, or at least a value based in the list being iterated on.

Personally I always put local vars outside the loop but this is really a
holdover from my days of writing real-time compilers in C++. It's not as
readable but it feels "faster" to me.

You should declare them outside only in the case that you need an especific
initial value that is not derived from the list being iterated, otherwise
IMO they should be put inside the loop


cheers,
 
P

Paul Robson

cody said:
No matter *where* the variables are located in the method: they all are
allocated only *once*.
But if you assign a value to them, e.g. int i=0; the assignment takes place
everytime this line of code is executed.
Surely they are allocated off the top of the stack, so will be allocated
on each loop entry, but this will only be whatever the .NET equivalent
of add sp,4 ; mov [sp-4],0 is ?
 
C

cody

Paul Robson said:
cody said:
No matter *where* the variables are located in the method: they all are
allocated only *once*.
But if you assign a value to them, e.g. int i=0; the assignment takes
place everytime this line of code is executed.
Surely they are allocated off the top of the stack, so will be allocated
on each loop entry, but this will only be whatever the .NET equivalent of
add sp,4 ; mov [sp-4],0 is ?

I think the allocation itself (add sp,4) will take place only once for each
call of that method.
But the assignment (mov [sp-4],0) will take place in every iteration of the
loop.
 
P

Peter Sestoft

Javaman59 said:
Using local declarations within a block often makes code more readable, but
is it less efficient? eg...
[...]
Any experts here who can ease my mind about the possible ineffiency of
nested variables?

As shown by others, it makes no difference in the IL whether you put
the declarations inside or outside.

So put them where they logically belong in your case: inside the
loop.

Once you use an anonymous method inside the loop it makes a great
(semantic, not just efficiency) difference whether you put it inside
or not.

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Declaring variables in loops 6
nested for loops 5
nested struct array 1
Exiting nested For loops 5
Nested Do While Loops 3
Implementing Nested Transaction in C# 1
Help on nested loops 1
RANGE & NESTED LOOPS 1

Top